TCP并发服务器(一)——每个客户一个子进程
1.说明
这是最传统的并发服务器,对于每一个客户请求fork一个子进程。问题在于每次fork一个子进程比较耗费时间,下面会讲预创建进程。
程序代码基于UNP的库。
程序在使用进程的模式下是最慢的。
2.代码
#include "unp.h"int main(int argc, char *argv[])
{int listenfd;socklen_t addrlen;if (argc = 2) {listenfd = Tcp_listen(NULL, argv[1], &addrlen);} else if (argc ==3) {listenfd = Tcp_listen(argv[1], argv[2], &addrlen);} else {err_quit("Usage: a.out [ <host> ] <port#>");}struct sockaddr *cliaddr = (struct sockaddr*)Malloc(addrlen);void sig_chld(int), sig_int(int), web_child(int);Signal(SIGCHLD, sig_chld);Signal(SIGINT, sig_int);for ( ; ;) {socklen_t clilen = addrlen; DPRINTF("Wait for a connection\n");int connfd = accept(listenfd, cliaddr, &clilen); //clilen用于值-结果参数,可能会改变,所以每次重新赋值,所以此处不能使用addrlenDPRINTF("Accept a connection\n");if (connfd < 0) {if (errno == EINTR) {continue;} else {err_sys("accept() error");}} pid_t childpid = Fork();if (childpid == 0) { //child processDPRINTF("Fork a child process\n");Close(listenfd); //close listening socketweb_child(connfd); //process requestexit(0);}Close(connfd); //parent closes connected socket} //end for(;;)return 0;
}void sig_int(int)
{DPRINTF("sig_int()\n");void pr_cpu_time(void);pr_cpu_time();exit(0);
}void sig_chld(int)
{static int cnt = 0;pid_t pid;int stat;//param1: 想要等待的PID;-1: 等待第一个终止的子进程//param2: 子进程的终止状态(整数)//param3: 附加选项;WNOHANG:没有子进程终止时,不阻塞while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { //成功:返回进程ID > 0, 出错:0或-1DPRINTF("Waitpid for %d child process\n", ++cnt);;}return;
}