//------------------------------------------------------------------- // tcpserver4.cpp // // This program revises the 'signal-handler' that we introduced // into our 'tcpserver3.cpp' example, to avoid a race-condition // whereby some child-processes may become 'zombies' if client- // connections are broken too rapidly for the signal-handler to // properly 'wait' for each child to exit in turn individually. // // to compile: $ g++ tcpserver4.cpp -o tcpserver4 // to execute: $ ./tcpserver4 // // programmer: ALLAN CRUSE // written on: 10 MAR 2009 //------------------------------------------------------------------- #include // for printf(), perror() #include // for exit() #include // for read(), write(), close() #include // for socket(), bind(), listen(), #include // for signal() #include // for wait() #define DEMO_PORT 54321 void sigchld_action( int signo ) { while ( waitpid( -1, NULL, WNOHANG ) > 0 ); signal( SIGCHLD, sigchld_action ); printf( "data was received, processed, and returned\n" ); printf( "\nserver is listening on port %u \n", DEMO_PORT ); } int main( int argc, char **argv ) { signal( SIGCHLD, sigchld_action ); //-------------------------------------------------- // create a socket-address structure for our socket //-------------------------------------------------- struct sockaddr_in haddr = { 0 }; socklen_t halen = sizeof( haddr ); haddr.sin_family = AF_INET; haddr.sin_port = htons( DEMO_PORT ); haddr.sin_addr.s_addr = htonl( INADDR_ANY ); //--------------------------------------------- // create the listening socket for this server //--------------------------------------------- int sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( sock < 0 ) { perror( "socket" ); exit(1); } //----------------------------------------------------- // bind this listening socket to our fixed port-number //----------------------------------------------------- if ( bind( sock, (sockaddr*)&haddr, halen ) < 0 ) { perror( "bind" ); exit(1); } //----------------------------------------------------- // create a connection queue for this listening socket //----------------------------------------------------- if ( listen( sock, 5 ) < 0 ) { perror( "listen" ); exit(1); } printf( "\nserver is listening on port %u \n", DEMO_PORT ); //------------------------------------------------ // enter the main look to process client requests //------------------------------------------------ do { //-------------------------------------------------- // accept the next connection-request from a client //-------------------------------------------------- struct sockaddr_in paddr = { 0 }; socklen_t palen = sizeof( paddr ); int conn = accept( sock, (sockaddr*)&paddr, &palen ); if ( conn < 0 ) { perror( "accept" ); exit(1); } //---------------------------------------------------- // fork a child-process to handle this new connection //---------------------------------------------------- int pid = fork(); if ( pid < 0 ) { perror( "fork" ); exit(1); } if ( pid > 0 ) { // parent closes the connection-socket close( conn ); continue; } //----------------------------------------------------- // child can now receive characters sent by the client //----------------------------------------------------- char buf[ 3000 ] = {0}; int len = sizeof( buf ); int rx = 0; while ( rx < len ) { int inch = 0; int i = read( conn, &inch, 1 ); if ( i < 0 ) { perror( "read" ); exit(1); } if ( i == 0 ) break; buf[ rx ] = inch; ++rx; } //----------------------------------------------- // convert all the received letters to uppercase //----------------------------------------------- for (int i = 0; i < rx; i++) if (( buf[i] >= 'a' )&&( buf[i] <= 'z' )) buf[i] += 'A' - 'a'; //---------------------------------------------- // send the modified message back to the client //---------------------------------------------- int tx = write( conn, buf, rx ); if ( tx < 0 ) { perror( "write" ); exit(1); } //---------------------------------------------------- // flush the output buffers and close this connection //---------------------------------------------------- fflush( fdopen( conn, "rw" ) ); close( conn ); exit( 0 ); } while( 1 ); }