第二章:TCP并发服务器(一)

发布于:2025-02-11 ⋅ 阅读:(63) ⋅ 点赞:(0)

作业:

多进程多线程并发服务器实现一遍提交。

多进程:

/*******************************************************/
//=> File Name: bingfaser.c
//=> Author: Water
//=> Mail: 1249496568@qq.com 
//=> Created Time: 2024年12月29日 星期日 14时08分42秒
/*******************************************************/

#include<myhead.h>
#define IP "192.168.124.71"
#define PORT 9999
void handle(int sss)
{
	if(sss == SIGCHLD)
	{
		while(waitpid(-1,NULL,WNOHANG) > 0);
	}
	printf("子进程回收成功\n");
}
int main(int argc, const char *argv[])
{
	//1、创建套接字
	int oldfd = socket(AF_INET,SOCK_STREAM,0);
	if(oldfd == -1)
	{
		perror("socket");
		return -1;
	}
	//快速复用
	int k = 1;
	if(setsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&k,sizeof(k)) == -1)
	{
		perror("setsockopt");
		return -1;
	}
	printf("端口号快速复用成功\n");
	//2、绑定
	struct sockaddr_in server = 
	{
		.sin_family = AF_INET,
		.sin_port = htons(PORT),
		.sin_addr.s_addr = inet_addr(IP)
	};
	if(bind(oldfd,(struct sockaddr *)&server,sizeof(server)) == -1)
	{
		perror("bind");
		return -1;
	}
	//3、监听
	if(listen(oldfd,88) == -1)
	{
		perror("listen");
		return -1;
	}
	//4、父进程连接新的客户端
	struct sockaddr_in client;
	int client_len = sizeof(client);
	while(1)
	{
		int newfd = accept(oldfd,(struct sockaddr *)&client,&client_len);
		if(newfd == -1)
		{
			perror("accept");
			return -1;
		}
		printf("客户端%s:%d已连接\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
		//5、创建子进程,父进程关闭新的描述符
		pid_t pid = fork();
		char buff[1024] = "";
		if(pid > 0)
		{
			if(signal(SIGCHLD,handle) == SIG_ERR) //绑定子进程退出时的信号
			{
				perror("signal");
				return -1;
			}
			close(newfd);
		}
		//6、子进程负责数据收发,关闭旧的描述符
		else if(pid == 0)
		{
			close(oldfd);
			while(1)
			{
				int res = recv(newfd,buff,sizeof(buff),0);
				if(res == 0)
				{
					printf("\n客户端%s:%d已退出\n",\
							inet_ntoa(client.sin_addr),ntohs(client.sin_port));
					break;
				}
				printf("\n客户端%s:%d发来信息:%s\n",\
						inet_ntoa(client.sin_addr),ntohs(client.sin_port),buff);
				strcat(buff,"\n服务器已接收\n");
				send(newfd,buff,sizeof(buff),0);
				bzero(buff,sizeof(buff));
			}
			exit(0);
		}
		else
		{
			perror("fork");
			return -1;
		}
	}
	close(oldfd);
	return 0;
}

 多线程:

/*******************************************************/
//=> File Name: bingfaser.c
//=> Author: Water
//=> Mail: 1249496568@qq.com 
//=> Created Time: 2024年12月29日 星期日 14时08分42秒
/*******************************************************/

#include<myhead.h>
#define IP "192.168.124.71"
#define PORT 9999
void * fun(void * fd)
{
	int newfd = *(int *)fd;
	char buff[1024];
	while(1)
	{
		int res = recv(newfd,buff,sizeof(buff),0);
		if(res == 0)
		{
			printf("\n客户端已退出\n");
			break;
		}
		printf("\n客户端发来信息:%s\n",buff);
		strcat(buff,"\n服务器已接收\n");
		send(newfd,buff,sizeof(buff),0);
		bzero(buff,sizeof(buff));
	}
	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	//1、创建套接字
	int oldfd = socket(AF_INET,SOCK_STREAM,0);
	if(oldfd == -1)
	{
		perror("socket");
		return -1;
	}
	//快速复用
	int k = 1;
	if(setsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&k,sizeof(k)) == -1)
	{
		perror("setsockopt");
		return -1;
	}
	printf("端口号快速复用成功\n");
	//2、绑定
	struct sockaddr_in server = 
	{
		.sin_family = AF_INET,
		.sin_port = htons(PORT),
		.sin_addr.s_addr = inet_addr(IP)
	};
	if(bind(oldfd,(struct sockaddr *)&server,sizeof(server)) == -1)
	{
		perror("bind");
		return -1;
	}
	//3、监听
	if(listen(oldfd,88) == -1)
	{
		perror("listen");
		return -1;
	}
	//4、主线程连接新的客户端
	struct sockaddr_in client;
	int client_len = sizeof(client);
	int newfd;
	pthread_t tid;
	while(1)
	{
		newfd = accept(oldfd,(struct sockaddr *)&client,&client_len);
		if(newfd == -1)
		{
			perror("accept");
			return -1;
		}
		printf("客户端%s:%d已连接\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
		//5、创建子线程,主线程关闭新的描述符
		if(pthread_create(&tid,NULL,fun,&newfd) == -1)
		{
			perror("pthread_create");
			return -1;
		}
	}
	pthread_join(tid,NULL); //回收子线程资源
	close(newfd);
	close(oldfd);
	return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到