多进程并发TCP服务器示例
程序逻辑:
1.TCP服务器先绑定本地地址信息,处于监听状态;
2.设置信号(SIGCHLD)时回收子进程;
2.在循环中等待连接;
3.当收到客户端连接,开启子进程,在子进程处理与客户端的通信操作(关闭掉监听套接字);
4.主进程关闭掉创建子进程创建生成的套接字;
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netinet/ip.h>
void child_process(int confd,struct sockaddr_in cl_addr)
{
char buf[1024]={0};
ssize_t read_len;
while(1)
{
memset(buf,0,sizeof(buf));
read_len=read(confd,buf,sizeof(buf));
if(read_len<0)
{
perror("Fail to read");
return ;
}
else if(read_len==0)
{
printf("客户端退出!\n");
break;
}
else
{
printf("[%s:%d]:",inet_ntoa(cl_addr.sin_addr),ntohs(cl_addr.sin_port));
if(strncmp(buf,"quit",4)==0)
{
printf("已退出!\n");
break;
}
printf("%s\n",buf);
write(confd,buf,strlen(buf));//收到消息再返回去
}
}
exit(EXIT_SUCCESS);
}
void child_wait(int arg)
{
waitpid(-1,NULL,WNOHANG);//当收到子进程退出,则立即回收他
return;
}
int main(int argc, const char *argv[])
{
pid_t pid;
int ret;
int sockfd,confd;
struct sockaddr_in saddr,caddr;
int client_len=0;
client_len=sizeof(caddr);
if(argc!=2)
{
fprintf(stderr,"usage:%s 8888",argv[0]);
return -1;
}
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("Fail to socket");
return -1;
}
printf("socket\n");
memset(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(atoi(argv[1]));
saddr.sin_addr.s_addr=htonl(INADDR_ANY);//这里一定要是htonl(),其它函数会发生段错误
ret=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
if(ret<0)
{
perror("Fail to bind");
return -1;
}
printf("bind\n");
ret=listen(sockfd,10);
if(ret<0)
{
perror("Fail to listen");
return -1;
}
if(signal(SIGCHLD,child_wait)==SIG_ERR)//子进程状态改变时给父进程发送信号回收掉子进程
{
perror("Fail to signal");
return -1;
}
while(1)
{
memset(&caddr,0,sizeof(caddr));
confd=accept(sockfd,(struct sockaddr *)&caddr,&client_len);
if(confd<0)
{
perror("Fail to accept");
return -1;
}
pid = fork();
if(pid<0)
{
perror("Fail to fork");
return -1;
}
else if(pid==0)
{
close(sockfd);//监听套接字
child_process(confd,caddr);
}
else
{
close(confd);//创建子进程的套接字
}
}
close(sockfd);
close(confd);
return 0;
}