Multi-Request Multi-Client Fork-Based TCP
/*****************************  Multi-Client TCP  ***************************/
#include <sys/types.h>   /*******  Demo of multi-client application.  *******/
#include <sys/socket.h>  /*******  This is the client.                *******/
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>

#define BIGBUF 50 
#define SIGPIPE_ERROR 1
#define CONNECT_ERROR 2
#define INTERRUPT     3
#define READ_ERROR    4

int active;

main()
{
     char buf[256];
     void set_up_signals(void);
     void readserver(int active, char *buf, int bufsize);
     void connect_to_server(void);
   
     set_up_signals(); 
     connect_to_server();

     while(printf("Enter string: "), memset(buf, 0, BIGBUF),
           fgets(buf, BIGBUF, stdin), strncmp(buf,"quit", 4))
     {
         writen(active,buf, 1);
         writen(acive, buf + 1, BIGBUF - 1);  /* Two writes so ignite SIGPIPE */
         memset(buf, 0, BIGBUF);
         readn(active,buf,BIGBUF);
         printf("From server: %s\n", buf);
     }
     memset(buf, 0, BIGBUF);
     strcpy(buf,"quit");
     writen(active, buf, 1);
     writen(active, buf + 1, BIGBUF - 1);
     close(active);
}


void set_up_signals(void)
{
     struct sigaction sa;
     void pipe_handler(int signum), term_handler(int signum);

     sigfillset(&sa.sa_mask);
     sa.sa_handler = pipe_handler;
     sa.sa_flags   = 0;
     sigaction(SIGPIPE, &sa, NULL);
     sa.sa_handler = term_handler;
     sigaction(SIGQUIT, &sa, NULL);
     sigaction(SIGINT,  &sa, NULL);
}
void connect_to_server()
{
     struct sockaddr_in sin;

     active = socket(AF_INET, SOCK_STREAM, 0);
     memset(&sin, 0, sizeof(struct sockaddr_in));
     sin.sin_port = htons(3144); 
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = inet_addr("153.18.17.11");

     if (connect(active, (struct sockaddr *)&sin, sizeof(sin)) == -1)
     {
        perror("Bad connection.");
        exit(CONNECT_ERROR);
     }
}



/****************************  SIGPIPE handler  *****************************/
void pipe_handler(int signum)
{
    printf("Server disconnected\n");
    exit(SIGPIPE_ERROR);
}


/*************************  Terminal signal handler  ************************/
void term_handler(int signum)
{
    char buf[BIGBUF] = {'\0'};

    memset(buf, 0, BIGBUF);
    strcpy(buf, "quit");
    writen(active, buf, BIGBUF);
    close(active);
    exit(INTERRUPT);
}


int readn(int fd, char *buf, int bytes)
{
     int nleft;
     int nread;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nread = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         else if (nread == 0)
              break;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}


int writen(int fd, char *buf, int bytes)
{
     int nleft;
     int nwritten;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nwritten = write(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}
#include <unistd.h>    /**********  This is the server.  *********/
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>

#define BIGBUF 50
#define BIND_ERROR   1
#define LISTEN_ERROR 2
#define ACCEPT_ERROR 3
#define FORK_ERROR   4
#define READ_ERROR   5
#define CLIENT_GONE  6
#define TIMED_OUT    7

int active, passive;

main()
{
     pid_t pid;
     int addr_len;
     char buf[256];
     struct sockaddr_in client;
     void set_up_signals(void);
     void create_passive_socket(void);
     void readn(int active, char *buffer, int buffer_size);
     void writen(int active, char *buffer, int buffer_size);
   
     set_up_signals();
     create_passive_socket();
  
     addr_len = sizeof(struct sockaddr_in);
     while (1)   /*****  Server stays alive for ever!!!  *****/
     {
         active = accept(passive, (struct sockaddr *)&client, &addr_len);
         if (active < 0) 
         {
              if (errno == EINTR)
              {
                   errno = 0;
                   continue;
              }
              else
              {
                   perror("Accept error!");
                   exit(ACCEPT_ERROR);
              }
         }

         if ((pid = fork()) < 0)
         {
              perror("Fork error!");
              exit(FORK_ERROR);
         }

         if (pid != 0)   /******  Parent  ******/
         {
              close(active);
              continue;
         }
         else    /******  Child  ******/
         {
              close(passive);
              while(alarm(10), memset(buf, 0, 256),
                    readn(active, buf, BIGBUF), strncmp(buf, "quit", 4))
              {
                    alarm(0);
                    writen(active, buf, BIGBUF);
              }         
              exit(0);   /*****  Don't forget this!!!!!  *****/
         }
      }   /***  end while(1)  ***/
}



/**************  Handle timeout/disappearance of client  **************/
void set_up_signals(void)
{
     struct sigaction sa;
     void alarm_handler(int signum), no_client(int signum),
          sigchld_handler(int signum);

     sigfillset(&sa.sa_mask);    /****  Take care of signals.  ****/
     sa.sa_flags   = 0;
     sa.sa_handler = alarm_handler;
     sigaction(SIGALRM, &sa, NULL);
     sa.sa_handler = no_client;
     sigaction(SIGPIPE, &sa, NULL);
     sa.sa_handler = sigchld_handler;
     sigaction(SIGCHLD, &sa, NULL);
}


void create_passive_socket(void)
{
     struct sockaddr_in sin;

     passive = socket(AF_INET, SOCK_STREAM, 0);
     memset(&sin, 0, sizeof(sin));
     sin.sin_port = htons(3144); 
     sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = htonl(INADDR_ANY);
     if (bind(passive, (struct sockaddr *)&sin, (socklen_t) sizeof(sin)) == -1)
     {
         perror("Binding error!");
         exit(BIND_ERROR);
     }
     if (listen(passive, 1) < 0)
     {
         perror("Listen error!");
         exit(LISTEN_ERROR);
     }
}
/*******************  Clear zombie when child finishes.  *********************/
void sigchld_handler(int signum)
{
     int status;

     while (waitpid(-1, &status, WNOHANG) > 0);
}


/***************  Close active socket when client disappears  ***************/
void no_client(int signum)
{
     close(active);
     exit(CLIENT_GONE);
}



/****************  Close active socket when client is timed out  *************/
void alarm_handler(int signum)
{
     close(active);
     exit(TIMED_OUT);
}


int readn(int fd, char *buf, int bytes)
{
     int nleft;
     int nread;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nread = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         else if (nread == 0)
              break;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}


int writen(int fd, char *buf, int bytes)
{
     int nleft;
     int nwritten;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nwritten = write(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}
/*****************************  Sample Session  **************************/

$ ms&
[1]     2110
$ mc
Enter string: hello
From server: hello

Enter string: goodbye
From server: goodbye

Enter string: [2] + Stopped                  mc
$ mc
Enter string: what
From server: what

Enter string: when
From server: when

Enter string: quit
$ fg
mc
who
Server disconnected
$ mc
Enter string: howdy!
From server: howdy!

Enter string: quit
$