linux网络编程之服务端程序(二)

/*
 * 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;
	void	sig_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子进程

你可能感兴趣的:(linux网络编程之服务端程序(二))