performance/tcpsserverconcurrent.c

///////////////////////////////////////////////////////////////////////////////
// Filename: tcpserverconcurrent.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: measures performance of a TCP connection (socket version)
//          uses tcpsclientthroughput(.c) as TCP client
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/03/01 16:52:19 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);
    }

    // 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

    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);
    }


    // 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 
    
                readdata(argv[0], "read", newsockfd); // process the request

                return(EXIT_SUCCESS);   // and exit..
            }

        close(newsockfd);               // parent process: close socket
                                        // to be able to reuse it for the
                                        // next connection
    }
}