多进程并发服务器
使用多进程并发服务器时要考虑以下几点:
1. 父进程最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符)
2. 系统内创建进程个数(与内存大小相关)
3. 进程创建过多是否降低整体服务性能(进程调度)
服务端 server
/*
多进程实现高并发服务器
*/
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<signal.h>
#include<sys/wait.h>
#include<strings.h>
#include<string.h>
#include<ctype.h>
#include"wrap.h"
#define SERV_PORT 8000
// “192.168.170.128”
void wait_child(int signo)
{
while(waitpid(0,NULL,WNOHANG)); // 进行非阻塞轮询回收子进程
return;
}
int main(void)
{
int lfd,cfd;
int i,n;
pid_t pid;
struct sockaddr_in serv_addr,clie_addr;
socklen_t clie_addr_len;
char buf[BUFSIZ];
char str[BUFSIZ];
lfd = Socket(AF_INET,SOCK_STREAM,0);
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// inet_pton(AF_INET,"192.168.170.132",&serv_addr.sin_addr.s_addr);
Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
Listen(lfd,128);
printf("Accept conection ...\n");
while(1)
{
clie_addr_len = sizeof(clie_addr);
cfd = Accept(lfd,(struct sockaddr*)&clie_addr,&clie_addr_len);
pid = fork();
if( pid < 0 )
{
perror("fork error");
exit(1);
}
else if(pid == 0 )
{
close(lfd);
break;
}
else
{
close(cfd);
signal(SIGCHLD,wait_child);
}
}
if(pid == 0)
{
while(1)
{
n = Read(cfd,buf,sizeof(buf));
if( n == 0 )
{
printf("the other side has been closed\n");
break;
}
printf("receive from %s at %d\n",
inet_ntop(AF_INET,&clie_addr.sin_addr,str,sizeof(str)),
ntohs(clie_addr.sin_port));
/*
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)),
ntohs(clie_addr.sin_port));
*/
for(i=0;i<n;i++)
buf[i] = toupper(buf[i]);
write(cfd,buf,n);
}
}
else if(pid>0)
{
Close(lfd);
}
else
{
perr_exit("fork");