这是我们的一次个并发服务程序,也是传统上应用的并发方式,服务器程序调用fork派生一个子进程来处理每个客户,这使得服务器能够同时为多个客户服务,每个进程负责一个客户。但是这里有一个限制,操作系统对一个进程能够同时拥有的子进程数是有限的,当客户数到达这个限制后,服务器程序就会fork出错,从而影响并发度。但这已经可以满足绝大多数需求了,所以绝大多数服务器程序也都是按照这个范式来编写的。
不过这种传统并发服务器也有一个问题,服务器程序为每个客户现场fork一个子进程比较耗费CPU时间。当一个服务器每天处理几百个或几千个客户时,这点CPU时间是可以接受的,然后现在繁重的web服务器每天接受的连接数以百万计。这还是就单个主机而言,更繁忙的站点往往运行多个主机来分摊(如利用DNS轮询来实施负载散布)。但是,这种传统意义上的并发服务器依然相当普遍。
每个客户一个子进程方式的并发服务程序也比较简单,其核心步骤如下:
for ( ; ; ) {
connfd = accept(listenfd, cliaddr, &clilen)
if ( (childpid = Fork()) == 0) { /* child process */
Close(listenfd); /* close listening socket */
...... /* deal with client's request */
exit(0);
}
Close(connfd); /* parent closes connected socket */
}
这种传统方式的并发服务程序实例如下,不再做过多解释:
serv01.c
------------------------
#include "global.h"
int main(int argc, char **argv) { int listenfd, connfd; pid_t childpid; void sig_chld(int), sig_int(int), web_child(int); socklen_t clilen, addrlen; struct sockaddr* cliaddr;
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: serv01 [ ] "); cliaddr = Malloc(addrlen);
Signal(SIGCHLD, sig_chld); Signal(SIGINT, sig_int);
for ( ; ; ) { clilen = addrlen; if ( (connfd = accept(listenfd, cliaddr, &clilen)) < 0) { if (errno == EINTR) continue; /* back to for() */ else err_sys("accept error"); }
if ( (childpid = Fork()) == 0) { /* child process */ Close(listenfd); /* close listening socket */ web_child(connfd); /* process request */ exit(0); } Close(connfd); /* parent closes connected socket */ } } /* end serv01 */
/* include sigint */ void sig_int(int signo) { void pr_cpu_time(void);
pr_cpu_time(); exit(0); } /* end sigint */
|
sig_chld()函数调用waitpid()来处理僵死子进程
sig_chld_waitpid.c
--------------------------
#include "global.h"
void sig_chld(int signo) { pid_t pid; int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) { /* printf("child %d terminated\n", pid); */ } return; }
|
每个客户一个子进程方式的执行结果如下:
$ ./serv01 173.26.100.162 12345
user time = 0.052002, sys time = 0.544033
程序源代码包见<<客户/服务器程序设计范式---迭代服务器程序>>后的附件
阅读(761) | 评论(0) | 转发(0) |