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