[ Team LiB ] |
30.3 TCP Test ClientFigure 30.3 shows the client that we will use to test all the variations of our server. 10–12 Each time we run the client, we specify the hostname or IP address of the server, the server's port, the number of children for the client to fork (allowing us to initiate multiple connections to the same server concurrently), the number of requests each child should send to the server, and the number of bytes to request the server to return each time. 17–30 The parent calls fork for each child, and each child establishes the specified number of connections with the server. On each connection, the child sends a line specifying the number of bytes for the server to return, and then the child reads that amount of data from the server. The parent just waits for all the children to terminate. Notice that the client closes each TCP connection, so TCP's TIME_WAIT state occurs on the client, not on the server. This is a difference between our client/server and normal HTTP connections. When we measure the various servers in this chapter, we execute the client as % client 192.168.1.20 8888 5 500 4000 This creates 2,500 TCP connections to the server: 500 connections from each of five children. On each connection, 5 bytes are sent from the client to the server ("4000\n") and 4,000 bytes are transferred from the server back to the client. We run the client from two different hosts to the same server, providing a total of 5,000 TCP connections, with a maximum of 10 simultaneous connections at the server at any given time.
We now present the nine different server designs. Figure 30.3 TCP client program for testing our various servers.server/client.c 1 #include "unp.h" 2 #define MAXN 16384 /* max # bytes to request from server */ 3 int 4 main(int argc, char **argv) 5 { 6 int i, j, fd, nchildren, nloops, nbytes; 7 pid_t pid; 8 ssize_t n; 9 char request[MAXLINE], reply[MAXN]; 10 if (argc != 6) 11 err_quit("usage: client <hostname or IPaddr> <port> <#children> " 12 "<#loops/child> <#bytes/request>"); 13 nchildren = atoi(argv[3]); 14 nloops = atoi(argv[4]); 15 nbytes = atoi(argv[5]); 16 snprintf(request, sizeof(request), "%d\n", nbytes); /* newline at end */ 17 for (i = 0; i < nchildren; i++) { 18 if ( (pid = Fork()) == 0) { /* child */ 19 for (j = 0; j < nloops; j++) { 20 fd = Tcp_connect(argv[1], argv[2]); 21 Write(fd, request, strlen(request)); 22 if ( (n = Readn(fd, reply, nbytes)) != nbytes) 23 err_quit("server returned %d bytes", n); 24 Close(fd); /* TIME_WAIT on client, not server */ 25 } 26 printf("child %d done\n", i); 27 exit(0); 28 } 29 /* parent loops around to fork() again */ 30 } 31 while (wait(NULL) > 0) /* now parent waits for all children */ 32 ; 33 if (errno != ECHILD) 34 err_sys("wait error"); 35 exit(0); 36 } |
[ Team LiB ] |