linux线程机制及webserver学习[上]

本文深入探讨了线程的基本概念及在Web服务器设计中的应用,包括线程的创建、等待、分工合作,以及如何利用线程处理客户端请求。通过具体代码示例,展示了如何在服务器中实现线程的安全操作,如互斥锁的使用,以及如何处理信号和资源回收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编写 web服务器 和 线程的使用

线程的基本使用(入门)

线程的定义

线程于函数相当于 进程于程序, 都给前者提供了运行环境

  • 线程三大性质

    1. 互斥
    2. 有限等待
    3. 前进
  • 几个编译时常量

线程的创建和等待
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,                 void *(*start_routine) (void *), void *arg);

int pthread_join(pthread_t thread, void **retval);
线程的分工合作
  • 互斥变量 (互斥)

// 加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
//解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
  • 条件变量(有限等待 + 前进性)
// 挂起本线程,自动解锁, 等待信号  (调用此函数前,要先上锁), 激活后自动加锁
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
// 发信号 (前进性)
int pthread_cond_signal(pthread_cond_t *cond);
代码
  • 头文件
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
// public variable
int count = 100;

// mutex lock
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// operator the public variable
void * show(void * a){
	while(1){
		pthread_mutex_lock(&mutex);
		if (count > 0 ) {

			printf("%s",(char *)a);
			printf("%d : %d\n",(int)pthread_self(),count --);
		}
		pthread_mutex_unlock(&mutex);
	}
}


int main(int argc, char *argv[])
{
	pthread_t t1;
	pthread_t t2;

	pthread_create(&t1,NULL,show,(void *)"hello");
	pthread_create(&t2,NULL,show,(void *)"world");
	pthread_join(t1,NULL);
	pthread_join(t2,NULL);
	return 0;
}

线程进程的相关性

在这里插入图片描述

服务器设计

创建socket , bind绑定 监听listening
  • 函数原型们
int socket(int domain, int type, int protocol);
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
int listen(int socket, int backlog);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
int close(int fildes);
int fscanf(FILE *stream, const char *format, ...);
  • 头文件们
// base fork
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/types.h>   
#include <sys/socket.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
// base thread

  • 服务器 创建socket 并绑定监听伪代码
int make_server_connect (int port){
	int state_socket ;
	int state_bind;
	int state_listen;

	struct sockaddr_in addr ;
	int  fd;

	if (-1 != (state_socket = socket(AF_INET,  SOCK_STREAM,0))){
		addr.sin_family=AF_INET;
		addr.sin_port=htons(port);
		addr.sin_addr.s_addr=INADDR_ANY;

		if(bind(state_socket, (const struct sockaddr *)&addr, sizeof(addr))==-1){
			perror("cannot bind");
			exit(1);
		}else {
			state_listen = listen(state_socket, 1);
			if (-1 == state_listen) {
				perror("cannot listen ")	;
				exit(3);
			}
			return state_socket;
		}
	}else {
		perror("cannot get socket")	;
		exit(2);
	}
}
服务器端接受和处理客户端请求(结合 fork )
  • 服务器端接受 伪代码
int main(int argc, char *argv[])
{
	char  request[1024];
	int interrupt = 1;	
	int fd;
	signal (SIGCHLD,MyWait);
	int socket = make_server_connect(9999);
	if (-1 == socket) {
		perror("make server connect fail")	;
		exit(4);
	}
	while (1){
		fd = accept(socket,NULL,NULL);	
		read(fd,request,sizeof(request));
		if (interrupt == 1 || -1 != fd  ) {
			interrupt = process(fd,request);			
			close(fd);
		}else{
			break;
		}
	}
	return 0;
}
  • SIGCHLD信号处理
void MyWait(int signum){
	while(waitpid(-1,NULL,WNOHANG)>0);//  用足够的wait 把所有的zombie进程去除(考虑多个信号同时到达的情况)
}
  • 处理客户端请求
int process (int fd,char * request){
	int fork_id = fork();
	char  cmd[1024];
	char  file_name[1024];
	char temp[1024];
	int ffd;
	int n;
	char buf[1024];
	switch (fork_id){
		case 0:
			sscanf(request,"%s%s%s",cmd,file_name,temp);

			if(strcmp(cmd,"GET")== 0){
				if((ffd=open(file_name+1, O_RDONLY))==-1){
					//handle_404(fd);
					printf("404");
					write(fd, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n", strlen("HTTP/1.1 404 Not Found\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n"));
					return 0;
				}
				printf("200");
				write(fd, "HTTP/1.0 200 OK\r\n\r\n", strlen("HTTP/1.0 200 OK\r\n\r\n"));
				while((n=read(ffd, buf, sizeof(buf)))>0){
						write(fd, buf, n);
					}
				close(ffd);
			}else{
				printf("400");
				write(fd, "HTTP/1.1 400 Operator Not Found\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n", strlen("HTTP/1.1 400 Operaor Not Found\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n"));
			}
			break;
		default:
			break;
	}
	return 1;
}

web服务器协议

http 1.1 和 http 1.0的区别

https://blog.youkuaiyun.com/ForgotAboutGirl/article/details/6936982

参考链接

API概览介绍: https://zh.wikipedia.org/wiki/POSIX线程

参考博客: https://blog.youkuaiyun.com/ithomer/article/details/5921003cd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值