首页 > 其他 > 详细

网络编程(5)多进程并发服务器

时间:2014-02-15 16:11:30      阅读:482      评论:0      收藏:0      [点我收藏+]
    多进程并发服务器基本流程是,accept接收一个客户端连接,就创建一个子进程来处理它,即一个子进程对应一个客户端。

简单说就是 父进程负责接收请求,子进程负责处理请求。


整理代码如下:

/*************************************************
Author: xiongchuanliang
Description: 多进程并发服务器,服务端代码
编译命令:
Linux:
g++ -o tcpserver_fork tcpserver_fork.cpp -m64 -I./common
**************************************************/

// 服务端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "initsock.h"
#include "common.h"

CInitSock initSock;

int main(int argc, char* argv[])
{
	int n = 0;

	//创建套接字
	SOCKET sListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(sListen == INVALID_SOCKET)
	{
		PrintError("socket() failed.\n");
		exit(EXIT_FAILURE);
	}

	//绑定本地IP和端口到套接字
	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVPORT); //大于1024且小于65535
	server_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(server_addr.sin_zero),8);

   //SO_REUSEADDR : 使bind函数能允许地址立即重用
	int on = 1;
	setsockopt( sListen, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on) );

	if(bind(sListen,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == SOCKET_ERROR)
    {
		PrintError("bind() failed.");
		exit(EXIT_FAILURE);
    }

    //开始监听
    if(listen(sListen, BACKLOG) == SOCKET_ERROR)
    {  
		PrintError("sListen() failed.");
        exit(EXIT_FAILURE);
    }

	struct sockaddr_in remoteAddr;
	socklen_t nAddrlen = sizeof(struct sockaddr_in);

	//循环接收数据
	while(1){	
		SOCKET sClient;				
		printf("等待客户端连接中...\n");	
		sClient = accept(sListen,(struct sockaddr *)&remoteAddr, &nAddrlen);		 
		if(sClient == INVALID_SOCKET)
		{
			PrintError("accept() failed.");
			continue;
		}
		printf("接收到一个客户端连接:%s \n",inet_ntoa(remoteAddr.sin_addr));
		//创建子进程,处理客户端连接
		if( (n=fork()) == 0)
		{
			char recvData[MAXDATASIZE]={0};
			//关闭监听套接字
			close(sListen);

			//接收数据
			int recvbytes = recv(sClient, recvData, MAXDATASIZE, 0);        
			if( recvbytes == 0)
			{
				printf("recv() no data!\n");
			}else if( recvbytes < 0)
			{
				PrintError("recv() failed");
			}else if(recvbytes > 0)
			{            
				recvData[recvbytes]=‘\0‘;
				printf("收到信息:%s\n",recvData);			
			}

			//发送数据到客户端
			char * sendData = "客户端,你好啊!\n";
			send(sClient, sendData, strlen(sendData), 0);
	      
			//关闭子进程连接的套接字	
			close(sClient);

			exit(EXIT_SUCCESS);
			//父进程准备接受下一个客户端的连接
		//}else if(n > 0){
		}else if(n < 0){
			printf("fork() failed! %s\n",strerror(errno));
			exit(EXIT_FAILURE);
		}
		//关闭套接字	
		close(sClient);
	}// end while

	
	exit(EXIT_SUCCESS);
}

注意在代码中出现父子各close(客户端连接)一次的原因是:
当fork()返回时后,与监听和连接描述符相关的文件表项的访问计数都加1.
所以都要各自关一次,计数才会为0,才是真正的关闭。

代码中用到的头文件在: 网络编程(1)跨平台的Socket同步阻塞工作模式例子


MAIL: xcl_168@aliyun.com

BLOG: http://blog.csdn.net/xcl168


网络编程(5)多进程并发服务器

原文:http://blog.csdn.net/xcl168/article/details/19218577

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!