performance/tcpsserverconcurrentoverhead.c
///////////////////////////////////////////////////////////////////////////////
// Filename: tcpserverconcurrentoverhead.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: needed for measurements by tcpsclientoverhead.c
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/02/29 11:40:52 muellerg: created
//
///////////////////////////////////////////////////////////////////////////////
// Feature test switches ///////////////////////////// Feature test switches //
    /* NONE */
// System headers /////////////////////////////////////////// System headers //
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#ifndef sun
#include <strings.h>
#endif
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
// Local headers ///////////////////////////////////////////// Local headers //
#include "../common.h"
// Macros /////////////////////////////////////////////////////////// Macros //
    /* NONE */
// File scope objects /////////////////////////////////// File scope objects //
const int BACKLOG = 5;      // maximum number of pending connections
// External variables, functions, and classes ///////////// External objects //
    /* NONE */
// Signal catching functions ///////////////////// Signal catching functions //
    /* NONE */
// Structures, unions, and class definitions /////////////////// Definitions //
    /* NONE */
// Functions and class implementation /// Functions and class implementation //
    /* NONE */
// Main /////////////////////////////////////////////////////////////// Main //
/*
 * Example of a concurrent server using the TCP protocol
 *
 * paramteters:
 *
 *   argv[1]: port number to bind() & listen() to
 */
int
main(int argc, char *argv[])
{
    error.set_program_name(argv[0]);    
    if(argc!=2)
    {
        cerr << "Usage: " << argv[0] << " port" << endl;
        exit(EXIT_FAILURE);
    }
    int sockfd, newsockfd, clilen, childpid;
    struct sockaddr_in  cli_addr, serv_addr;
    int portnumber = -1;
    // get port number
    portnumber = atoi(argv[1]);
    if(portnumber <1)
    {
        cerr << "illegal port number" << endl;
        exit(EXIT_FAILURE);
    }
    // establish a function that changes the signalhandler
    // to report child death so that they can be catched and 
    // zombie processes are avoided
#ifndef hpux
    catch_children();
#endif
    // create a TCP socket (an Internet stream socket)
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        error.system("server: can't create stream socket");
    // bind local address so that the client can send to us
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port        = htons(portnumber);
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        error.system("server: can't bind local address");
    // listen for connection on socket with a maximum length of
    // pending connections
    listen(sockfd, BACKLOG);
    while(true)
    {
        // wait for a connection from a client process.
        // This server is an example of a concurrent server.
         
        clilen = sizeof(cli_addr);
        // check for zombies
        waitpid(WAIT_ANY, NULL, WNOHANG);
        // accept connection
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd < 0)
            error.system("server: accept error");
        // spawn child process to handle request
    
        if ( (childpid = fork()) < 0)
            error.system("server: fork error");
        else
            if (childpid == 0)
            {   // child process 
                close(sockfd);          // close original socket 
    
                // do nothing for performance measurement
                return(EXIT_SUCCESS);   // and exit..
            }
        close(newsockfd);               // parent process: close socket
                                        // to be able to reuse it for the
                                        // next connection
    }
}