博客
关于我
(六)多进程实现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/

你可能感兴趣的文章
英语02_单词词性
查看>>
C语言12_预处理 #
查看>>
低通滤波器的设计
查看>>
窄带随机过程的产生
查看>>
随机四则运算
查看>>
Maven
查看>>
Java重载overload
查看>>
Java面向对象
查看>>
JAVA带标签的break和continue
查看>>
Java_File类的基本用法
查看>>
Java获取线程基本信息的方法
查看>>
JavaWeb用户信息管理系统-创建登录业的务持久层
查看>>
SpringIoC和DI注解开发
查看>>
Java类和对象
查看>>
Java集合Collection
查看>>
SpringMVC入门-概述和基本配置
查看>>
SpringBoot快速入门
查看>>
医疗管理系统-手机快速登录和SpringSecurity权限控制
查看>>
SpringCloud微服务简介
查看>>
网页实现微信登录
查看>>