/*
* server.c
*
* Created on: Nov 18, 2012
* Author: fsxchen
* Version 2:能够捕捉子进程结束信号SIGCHLD,防止僵尸进程的生成
* 前一个版本,子进程结束,僵尸进程生成
*/
#include
#include
#include
#include
#include
#include
#include
#include
//#include "sigchildwait.c"
#define PORT 8888
#define BACKLOG 2
void process_conn_server(int sock);
void sig_chld(int signo);
int main()
{
int sSock, cSock;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
voidsig_chld(int);
int err;
pid_t pid;
sSock = socket(AF_INET, SOCK_STREAM, 0); //创建一个TCP套接字
if(-1 == sSock)
{
printf("Create socket error");
return -1;
}
bzero(&server_addr, sizeof(server_addr)); //初始化地址空间
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
err = bind(sSock, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(err < 0)
{
printf("bind error");
return -1;
}
printf("Bind prigram is right,it return %d\n",err);
err = listen(sSock, BACKLOG);
if(err < 0)
{
printf("listen error");
return -1;
}
printf("Listen prigram is right,it return %d\n",err);
signal(SIGCHLD, sig_chld);
for( ; ; )
{
socklen_t addrlen = sizeof(struct sockaddr);
cSock = accept(sSock, (struct sockaddr*)&client_addr, &addrlen);
perror("The state is:");
pid = fork();
if(pid < 0)
{
printf("can't create new pid");
return -1;
}
if(pid == 0)
{
close(sSock);
process_conn_server(cSock);
exit(0);
}
else
close(cSock);
}
return 0;
}
void process_conn_server(int sock)
{
ssize_t size = 0;
char buffer[1024];
for( ; ; )
{
size = read(sock, buffer, 1024);//当读到的字节位0,即发送方停止发送,就会返回
if(size == 0)
return;
//sprintf(buffer, "%d bytes altogether\n", (int)size);
write(STDOUT_FILENO, buffer, strlen(buffer) +1 );
//printf(buffer);
}
}
void
sig_chld(int signal)
{
pid_t pid;
int stat;
pid = wait(&stat);
printf("child %d terminal\n", pid);
return;
}
在前面,写过一个服务器的小代码,针对第一个版本的代码,如下分析,使用了fork函数,当一个客户端来请求数据的时候,fork函数被调用,创建一个子进程,此时父进程的socket执行close,继续后台监听。而此时子进程和客户端进行通信。但是,在这个过程中,如果子进程结束后,子进程会成为一个僵尸进程(关于进程知识,前面有相关博文),原因就是父进程没有wait子进程,并且,子进程在退出时的signal被忽略了,所以,这里的改进就是捕捉了子进程结束时候的信号,然后让父进程wait子进程