您的位置:首页 > 理论基础 > 计算机网络

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

2014-02-15 01:04 351 查看
    多进程并发服务器基本流程是,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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息