//------------------------------------------------------------------- // tcpserver3.cpp // // This program modifies our 'concurrent server' implementation // (titled 'tcpserver2.cpp') to employ a signal-handler for the // SIGCHLD signal, so that a child-process which exits will get // 'waited for' by its parent rather than endure as a 'zombie'. // (The user may terminate this server by hitting -C.) // // to compile: $ g++ tcpserver3.cpp -o tcpserver3 // to execute: $ ./tcpserver3 // // programmer: ALLAN CRUSE // written on: 09 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 ) { // a child has exited, so we know 'wait()' will not block wait( NULL ); // but now we need to reinstall the signal-handler signal( SIGCHLD, sigchld_action ); // and display our confirmation messages 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 ); }