[ Team LiB ] |
30.10 TCP Concurrent Server, One Thread per ClientThe last five sections have focused on one process per client, both one fork per client and preforking some number of children. If the server supports threads, we can use threads instead of child processes. Our first threaded version is shown in Figure 30.26. It is a modification of Figure 30.4 that creates one thread per client, instead of one process per client. This version is very similar to Figure 26.3. Main thread loop19–23 The main thread blocks in a call to accept and each time a client connection is returned, a new thread is created by pthread_create. The function executed by the new thread is doit and its argument is the connected socket. Per-thread function25–33 The doit function detaches itself so the main thread does not have to wait for it and calls our web_client function (Figure 30.3). When that function returns, the connected socket is closed. Figure 30.26 main function for TCP threaded server.server/serv06.c 1 #include "unpthread.h" 2 int 3 main(int argc, char **argv) 4 { 5 int listenfd, connfd; 6 void sig_int(int); 7 void *doit(void *); 8 pthread_t tid; 9 socklen_t clilen, addrlen; 10 struct sockaddr *cliaddr; 11 if (argc == 2) 12 listenfd = Tcp_listen(NULL, argv[1], &addrlen); 13 else if (argc == 3) 14 listenfd = Tcp_listen(argv[1], argv[2], &addrlen); 15 else 16 err_quit("usage: serv06 [ <host> ] <port#>"); 17 cliaddr = Malloc(addrlen); 18 Signal(SIGINT, sig_int); 19 for ( ; ; ) { 20 clilen = addrlen; 21 connfd = Accept(listenfd, cliaddr, &clilen); 22 Pthread_create(&tid, NULL, &doit, (void *) connfd); 23 } 24 } 25 void * 26 doit(void *arg) 27 { 28 void web_child(int); 29 Pthread_detach(pthread_self()); 30 web_child((int) arg); 31 Close((int) arg); 32 return (NULL); 33 } We note from Figure 30.1 that this simple threaded version is faster than even the fastest of the preforked versions. This one-thread-per-client version is also many times faster than the one-child-per-client version (row 1).
|
[ Team LiB ] |