unix网络编程各种TCP客户-服务器程序设计实例(四)
第六种 TCP预先派生子进程服务器程序,每个线程各自accept:
预先派生一个子进程池,每个线程各自调用accept接受连接,不过我们不是让每个线程都阻塞在accept调用上,而是直接使用互斥锁来保证线程间互斥地调用accept。
客户端程序还是和unix网络编程各种TCP客户-服务器程序设计实例(三)中的一样,这里就不讲了,我们着重看服务器的程序:
pthread.h:
typedef struct { pthread_tthread_tid;/* thread ID */ longthread_count;/* # connections handled */} Thread;Thread*tptr;/* array of Thread structures; calloc'ed */intlistenfd, nthreads;socklen_taddrlen;pthread_mutex_tmlock;
pthread.c
#include"unpthread.h"#include"pthread.h"voidthread_make(int i){void*thread_main(void *);Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void *) i);return;/* main thread returns */}void *thread_main(void *arg){intconnfd;voidweb_child(int);socklen_tclilen;struct sockaddr*cliaddr;cliaddr = Malloc(addrlen);printf("thread %d starting\n", (int) arg);for ( ; ; ) {clilen = addrlen; Pthread_mutex_lock(&mlock);connfd = Accept(listenfd, cliaddr, &clilen);Pthread_mutex_unlock(&mlock);tptr[(int) arg].thread_count++;web_child(connfd);/* process request */Close(connfd);}}
web_child.c
#include"unp.h"#defineMAXN16384/* max # bytes client can request */voidweb_child(int sockfd){intntowrite;ssize_tnread;charline[MAXLINE], result[MAXN];for ( ; ; ) {if ( (nread = Readline(sockfd, line, MAXLINE)) == 0)return;/* connection closed by other end *//* 4line from client specifies #bytes to write back */ntowrite = atol(line);if ((ntowrite <= 0) || (ntowrite > MAXN))err_quit("client request for %d bytes", ntowrite);Writen(sockfd, result, ntowrite);}}
pr_cpu_time.c
#include"unp.h"#include<sys/resource.h>#ifndefHAVE_GETRUSAGE_PROTOintgetrusage(int, struct rusage *);#endifvoidpr_cpu_time(void){doubleuser, sys;struct rusagemyusage, childusage;if (getrusage(RUSAGE_SELF, &myusage) < 0)err_sys("getrusage error");if (getrusage(RUSAGE_CHILDREN, &childusage) < 0)err_sys("getrusage error");user = (double) myusage.ru_utime.tv_sec +myusage.ru_utime.tv_usec/1000000.0;user += (double) childusage.ru_utime.tv_sec + childusage.ru_utime.tv_usec/1000000.0;sys = (double) myusage.ru_stime.tv_sec + myusage.ru_stime.tv_usec/1000000.0;sys += (double) childusage.ru_stime.tv_sec +childusage.ru_stime.tv_usec/1000000.0;printf("\nuser time = %g, sys time = %g\n", user, sys);}
server.c
/* include serv07 */#include"unpthread.h"#include"pthread.h"pthread_mutex_tmlock = PTHREAD_MUTEX_INITIALIZER;intmain(int argc, char **argv){inti;voidsig_int(int), thread_make(int);if (argc == 3)listenfd = Tcp_listen(NULL, argv[1], &addrlen);else if (argc == 4)listenfd = Tcp_listen(argv[1], argv[2], &addrlen);elseerr_quit("usage: serv07 [ <host> ] <port#> <#threads>");nthreads = atoi(argv[argc-1]);tptr = Calloc(nthreads, sizeof(Thread));for (i = 0; i < nthreads; i++)thread_make(i);/* only main thread returns */Signal(SIGINT, sig_int);for ( ; ; )pause();/* everything done by threads */}/* end serv07 */voidsig_int(int signo){inti;voidpr_cpu_time(void);pr_cpu_time();for (i = 0; i < nthreads; i++)printf("thread %d, %ld connections\n", i, tptr[i].thread_count);exit(0);}
编译命令:
gcc server.c pthread.c pr_cpu_time.c web_child.c -o server -lunp -lpthread