博客
关于我
(六)多进程实现TCP服务端
阅读量:316 次
发布时间:2019-03-04

本文共 3094 字,大约阅读时间需要 10 分钟。

首先,为什么要用多进程处理,多进程的好处是可靠性高,而且在处理大量数据的时候,多进程的速度会比多线程快,所有多进程还是要掌握的。

在一些实际项目中,进程和线程要根据实际场景用。

但是多进程是不能共享进程空间的,所以有很多变量都不能共享。除了fork()之前的变量是可以共享的。


下面的代码基本逻辑就是,用父进程来 accept,检测有没有新的客户端要连入,用子进程来接受客户端发来的信息


下面给出服务端的代码:(有详细注释)

#include"myhead.h"char rbuf[50];char wbuf[50];char ipbuf[50];int main(){	signal(SIGCHLD,SIG_IGN);//把子进程的僵尸进程给init进程处理 	struct sockaddr_in saddr;	struct sockaddr_in caddr;	int size,len,opt = 1;	int sockfd,newfd;	pid_t pid;	int err;	size = sizeof(struct sockaddr_in);	len = sizeof(struct sockaddr);	//初始化本地ip,地址信息	bzero(&saddr,size);	saddr.sin_family = AF_INET;	saddr.sin_port = htons(8888);	saddr.sin_addr.s_addr = htonl(INADDR_ANY);	//创建一个监听套接字	sockfd = socket(AF_INET,SOCK_STREAM,0);	if(sockfd<0)	{		perror("failed socket");		return -1;	}	//设置端口复用	err = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);	if(err<0)	{		perror("setsockopt failed");		return -1;	}	//绑定套接字和IP,地址信息	err = bind(sockfd,(struct sockaddr*)&saddr,len);	if(err<0)	{		perror("failed bind");		return -1;	}	//开始监听	listen(sockfd,10);	//循环接收 客户端的连入	while(1)	{		//监测有没有新的客户端连入,有的话,返回新的套接字		newfd = accept(sockfd,(struct sockaddr*)&caddr,&len);		if(newfd<0)		{			perror("accept failed");			continue;		}		//有新的客户端连入,则打印他的IP和端口		inet_ntop(AF_INET,(void*)&caddr.sin_addr.s_addr,						ipbuf,50);		printf("the client:%s is in\n",				ipbuf);		//创建一个子进程来接受新客户端的信息		pid = fork();		if(pid<0)   //fork失败		{			perror("failed fork()");			return -1;		}		else if(pid == 0)	//子进程		{				close(sockfd);//关闭从父进程进程来的监听套接字						  //因为在子进程用不到						  /*关闭不需要的套接字可节省系统资源,               同时可避免父子进程共享这些套接字               可能带来的不可预计的后果             */  			//这个子进程循环接收客户端信息			while(1)			{				err = recv(newfd,rbuf,50,0);				if(err<0)				{					perror("failed recv");				}									//若recv的返回=0,表示客户端已经断开					else if(err == 0)				{					bzero(ipbuf,50);					inet_ntop(AF_INET,(void*)&caddr.sin_addr.s_addr,						ipbuf,50);					printf("the client:%s is out\n",						ipbuf);					exit(0);					close(newfd);									}				//读取客户端的信息				else				{					inet_ntop(AF_INET,(void*)&caddr.sin_addr.s_addr,						ipbuf,50);					printf("ip:%s,port:%d\n",ipbuf,ntohs(caddr.sin_port));					printf("%s\n",rbuf);					bzero(rbuf,50);				}			}		}		else if(pid>0)  //父进程,用于继续监测有没有新的客户端连入		{			close(newfd);//关闭新客户端返回的套接字,因为在						//父进程中用不到			continue;		}	}}

再给出客户端的代码:
客户端的没啥好说的,通用的客户端代码就可以
#include "myhead.h"char wbuf[50];int main(){	struct sockaddr_in saddr;	struct sockaddr_in caddr;	int size,len,opt = 1;	int sockfd,newfd;	pid_t pid;	int err;	size = sizeof(struct sockaddr_in);	len = sizeof(struct sockaddr);	bzero(&saddr,size);	saddr.sin_family = AF_INET;	saddr.sin_port = htons(8888);	saddr.sin_addr.s_addr = inet_addr("192.168.106.128");	sockfd = socket(AF_INET,SOCK_STREAM,0);	if(sockfd<0)	{		perror("failed socket");		return -1;	}	err = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);	if(err<0)	{		perror("setsockopt failed");		return -1;	}	err = connect(sockfd,(struct sockaddr*)&saddr,		sizeof(struct sockaddr));	if(err<0)	{		perror("failed connect");		return -1;	}	while(1)	{		scanf("%s",wbuf);		write(sockfd,wbuf,50);		bzero(wbuf,50);	}}




转载地址:http://oqfh.baihongyu.com/

你可能感兴趣的文章
10分钟实现个人博客布置说说留言功能,Artitalk.js插件使用
查看>>
眼睛跟随鼠标转动的小黄人 html+css+js
查看>>
canvas贪吃蛇效果 html+css+js
查看>>
跟随鼠标移动的星星✩直接在页面引用✧✧✧
查看>>
poj 3660 (floyd)
查看>>
8086汇编语言21键电子琴
查看>>
找密码
查看>>
Python初级知识总结
查看>>
python|画图1(蛇)
查看>>
婚姻稳定匹配问题
查看>>
C++数据类型,运算符,注释
查看>>
C++语句,函数,标准输入输出
查看>>
平均年龄,,数字求和
查看>>
简单的字符串操作(注意要点)
查看>>
统计字符数
查看>>
C与C++区别
查看>>
JS 数组的 every()、some() 、filter()、findIndex() 、find()、map()方法
查看>>
原生 JS 封装的一些方法 【更新中...】
查看>>
Vue Element UI Upload 上传多张图片
查看>>
JS数据类型的判断
查看>>