
tcpserv.c
Go to the documentation of this file.
00001 /* tcpserv.c */ 00002 /* linked with wrapsock */ 00003 /* Client module */ 00004 /* Author: Michèle Garoche */ 00005 /* Date: February 26th 2003 00006 /* Feel free to do what you want with it */ 00007 00032 /* Includes */ 00033 #include "wrapsock.h" 00034 00041 int main(int argc, char *argv[]) 00042 { 00043 /* Variables */ 00047 int listenfd; /* passive sockets' file descriptors */ 00051 int connfd; /* active sockets' file descriptors */ 00055 int chopt; /* dummy variable for options test */ 00059 int port_served = 0; /* port to connect */ 00063 pid_t childpid; /* pid of the child process */ 00067 socklen_t clilen; /* size of the client's address structure */ 00071 char progname[MAXLINE]; /* program's name */ 00075 struct sockaddr_in cliaddr; /* client address structure */ 00079 struct sockaddr_in servaddr; /* server's address structure */ 00080 00081 /* Functions */ 00086 void sig_chld(int signo); /* function to catch the end of child process */ 00087 00088 /* Retrieve the program's name */ 00090 strcpy(progname, argv[0]); 00091 00092 /* The user should supplied an option for port. 00093 As the first argument is the program name, we should have 00094 2 arguments */ 00096 if (argc != 2) 00097 { 00098 /* Display the help and quit */ 00099 servusage(progname); 00100 } 00101 00102 /* Check for a valid option */ 00104 while ((chopt = getopt(argc, argv, "abch")) != -1) 00105 { 00106 switch (chopt) 00107 { 00108 case 'a': 00109 { 00110 port_served = 1; 00111 break; 00112 } 00113 case 'b': 00114 { 00115 port_served = 2; 00116 break; 00117 } 00118 case 'c': 00119 { 00120 port_served = 3; 00121 break; 00122 } 00123 case 'h': 00124 default: 00125 { 00126 /* Display help and quit */ 00127 servusage(progname); 00128 } 00129 } 00130 } 00131 00132 /* Compute the real port number */ 00133 port_served = port_served + SERV_PORT1 - 1; 00134 00135 /* Display help and quit if the argument for port is supplied without a dash before it */ 00137 if (port_served < SERV_PORT1 || port_served > SERV_PORT3) 00138 { 00139 servusage(progname); 00140 } 00141 00142 /* Help message for the user */ 00144 fprintf(stdout, "\nThe server %s will be attached to port %d.\n" 00145 "Its pid is %d.\n\nIf you have launched the server as a " 00146 "background process,\nreturn to continue and launch clients." 00147 "\nYou will have to kill the server with:\n kill -9 %d\n" 00148 "when finishing with it.\n\nIf you have launched the server" 00149 "as a foreground process,\nopen a new terminal to launch a " 00150 "client.\nYou will have to type:\n ctrl-C\nto quit the " 00151 "server when finishing with it." 00152 "\n\n", progname, port_served, (int)getpid(), (int)getpid()); 00153 00154 /* Create the socket */ 00156 listenfd = Socket(AF_INET, SOCK_STREAM, 0); 00157 00158 /* Fill in the address structure */ 00160 bzero(&servaddr, sizeof(servaddr)); 00161 servaddr.sin_family = AF_INET; 00162 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 00163 servaddr.sin_port = htons(port_served); 00164 00165 /* Attach the socket to the address */ 00167 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); 00168 00169 /* Convert the active socket into passive socket */ 00171 Listen(listenfd, LISTENQ); 00172 00173 /* Set the signal to catch the end of child's process */ 00175 Signal(SIGCHLD, sig_chld); 00176 00178 for ( ; ; ) 00179 { 00180 clilen = sizeof(cliaddr); /* retrieve the size of address structure */ 00181 00182 /* Duplicates the listening socket */ 00183 if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) 00184 { 00185 /* Accept was interrupted by system call - so restart it manually if needed */ 00186 if (errno == EINTR) 00187 { 00188 continue; 00189 } 00190 /* Any other error */ 00191 else 00192 { 00193 err_sys("accept error"); 00194 } 00195 } 00196 00197 /* Fork a process for answering each client's request */ 00198 if ( (childpid = Fork()) == 0) 00199 { 00200 /* Process Pi */ 00201 00202 /* Close the listening socket on child side */ 00203 Close(listenfd); 00204 00205 /* Perform the requested job */ 00206 switch (port_served) 00207 { 00208 case SERV_PORT1: 00209 { 00210 str_serv1(connfd); 00211 break; 00212 } 00213 case SERV_PORT2: 00214 { 00215 str_serv2(connfd); 00216 break; 00217 } 00218 case SERV_PORT3: 00219 { 00220 str_serv3(connfd); 00221 break; 00222 } 00223 } 00224 00225 exit(EXIT_SUCCESS); 00226 } 00227 00228 /* Parent closes connected socket */ 00229 /* End of child is handled by Signal function */ 00230 Close(connfd); 00231 } 00232 00233 /* Never goes here, just to be consistent with main's declaration */ 00234 return 0; 00235 }