简单的多进程并发服务器
服务器端代码如下:
#include"mylib.h"
int ipv4_tcp_creat_socket(void)
{
int opt;
socklen_t len;
int listenfd;
struct sockaddr_in server;
if((listenfd = socket(AF_INET,SOCK_STREAM,0))<0)
{
perror("Creat socket failed\n");
return -1;
}
//监听套接字,地址可重用
if((setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)))<0)
{
perror("Error,set socket reuse addr failed\n");
return -2;
}
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(SERV_PROT);
//server.sin_addr.s_addr = inet_addr("127.0.0.1");
//inet_pton(AF_INET,"127.0.0.1",&server.sin_addr);
server.sin_addr.s_addr = htonl(INADDR_ANY);
len = sizeof(struct sockaddr);
if(bind(listenfd,(struct sockaddr*)(&server),len)<0)
{
perror("bind error\n");
return -3;
}
listen(listenfd,MAX_LISTEN_QUE);
return listenfd;
}
int process_data(int sockfd)
{
int bytes;
char read_buf[MAX_BUFFER_SIZE];
memset(read_buf,0x00,MAX_BUFFER_SIZE);
while(1)
{
bytes = recv(sockfd,read_buf,100,0);
if(bytes<0)
{
printf("read err\n");
return -1;
}
if(bytes == 0)
{
printf("client connect closed\n");
//close(sockfd);
return 0;
}
printf("Bytes:%d\n",strlen(read_buf));
printf("read_buf:%c %c %c\n",read_buf[0],read_buf[1],read_buf[2]);
if(read_buf[0]=='Q')
{
return 0;
}
if(!strcmp(read_buf,"Tony"))
{
printf("I received Tony\n");
sprintf(read_buf,"%s","I received Tony\n");
send(sockfd,read_buf,strlen(read_buf),0);
}
else
{
send(sockfd,read_buf,bytes,0);
}
memset(read_buf,0x00,MAX_BUFFER_SIZE);
}
close(sockfd);
return 0;
}
//信号处理函数
int process_signal(int signo)
{
switch(signo)
{
case SIGCHLD:
printf("The client disconnected\n");
//-1表示所以进程 回收
while(waitpid(-1,NULL,WNOHANG)>0);
break;
}
}
int set_signal_handler(void)
{
struct sigaction act,oact;
act.sa_handler = (void *)process_signal;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
//SA_RESTART 被信号中断的系统调用会自行重启
act.sa_flags |= SA_RESTART;
if(sigaction(SIGCHLD,&act,&oact)<0)
{
return -1;
}
return 0;
}
int main(int argc,char *argv[])
{
int listenfd,sockfd;
socklen_t len;
int bytes = 0;
struct sockaddr_in server,client;
set_signal_handler();
len = sizeof(struct sockaddr);
listenfd = ipv4_tcp_creat_socket();
while(1)
{
sockfd = accept(listenfd,(struct sockaddr *)&client,&len);
if(sockfd<0)
{
perror("accept error\n");
return -1;
}
printf("sockfd = %d\n",sockfd);
printf("IP:%s,Port:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
if(fork()==0)
{
close(listenfd);
process_data(sockfd);
exit(0);
}
close(sockfd);
}
return 0;
}
实验结果:
客户端关闭时服务器会杀死其僵尸进程