Single-Threaded TCP With Select
#include "funcs.h"

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

int active;

main()
{
     char buf[BIGBUF];
     void set_up_signals(void);
     void readn (int active, char *buf, int bufsize);
     void writen(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))
     {
         buf[strlen(buf) - 1] = '\0';  /*  Get rid of \n  */
         writen(active,buf,1); 
         writen(active, buf + 1, BIGBUF - 1);
         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(PF_INET, SOCK_STREAM, 0);
     memset(&sin, 0, sizeof(struct sockaddr_in));
     sin.sin_port = htons(3014); 
     sin.sin_family = AF_INET;
     inet_aton("153.18.17.11", &sin.sin_addr);
     if (connect(active, (struct sockaddr *) &sin, sizeof(sin)) == -1)
     {
        perror("Bad connection.");
        exit(CONNECT_ERROR);
     }
}




void pipe_handler(int signum)
{
    printf("Server disconnected\n");
    close(active);
    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, 1);
    writen(active, buf + 1, BIGBUF - 1);
    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)
             raise(SIGPIPE);
         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 "funcs.h"

#define BUFSIZE   50
#define NOT_USED -1

int readsock;
sigjmp_buf env;
fd_set saveset;

struct timetable
{
    int socket;
    time_t requesttime;
};
struct timetable reqtimes[100];

main()
{
    void readn(int readsock, char *string, int bufsize);
    void set_up_SIGPIPE(void);
    fd_set readset;
    int socket, passive, active, lowwater = 50, i;
    char string[50];
    int set_up_passive_socket(void);
    int socklen = sizeof(int); 
    set_up_SIGPIPE();
    passive = set_up_passive_socket();

    FD_ZERO(&saveset);
    FD_SET(passive, &saveset);
    for (i = 0; i < 100; i++) reqtimes[i].socket  = NOT_USED;


    for(;;)
    {
         memcpy(&readset, &saveset, sizeof(fd_set));
         select(FD_SETSIZE, &readset, NULL, NULL, NULL);

         for (socket = 0; socket < 100; socket++)
         {
              if (reqtimes[socket].socket == NOT_USED) continue;
              if (time(NULL) - reqtimes[socket].requesttime > 10)
              {
                  close(socket);
                  FD_CLR(socket, &saveset);
                  reqtimes[socket].socket = NOT_USED;
              }
         }

         if (FD_ISSET(passive, &readset))
         {
              active = accept(passive, NULL, NULL);
              setsockopt(active, SOL_SOCKET, SO_RCVLOWAT, &lowwater, socklen);
              reqtimes[active].socket      = active;
              reqtimes[active].requesttime = time(NULL);
              FD_SET(active, &saveset);
         }
  

         for(readsock = passive; readsock < FD_SETSIZE  ; readsock++)
         {
              sigsetjmp(env, 1);
              if (readsock != passive && FD_ISSET(readsock, &readset))
              {
                    printf("Inside server!  Socket is %d.\n", readsock);

                    memset(string, 0, BUFSIZE);
                    readn(readsock, string, BUFSIZE);

                    if (strcmp(string, "quit") == 0)
                    {
                         FD_CLR(readsock, &saveset);
                         close(readsock);
                         reqtimes[readsock].socket = NOT_USED; 
                         continue;
                    }

                    printf("Got %s from client!\n", string);
                    writen(readsock, string, 1);
                    writen(readsock, string + 1, BUFSIZE - 1);
              }
         }  
     }           
}    




int set_up_passive_socket(void)
{
    struct sockaddr_in sin;
    int passive;

    sin.sin_family = AF_INET;
    sin.sin_port   = htons(3014);
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
 
    if  ((passive = socket(AF_INET,SOCK_STREAM,0)) < 0) 
    {
         perror("Server: socket error!");
         exit(1);
    }
    if (bind(passive, (struct sockaddr *) &sin, sizeof(sin)) < 0)
    {
         perror("Binding error in server!");
         exit(2);
    }
    if (listen(passive, 5) < 0)
    {
         perror("Listen error in server!");
         exit(3);
    }
    return passive;
}


void set_up_SIGPIPE(void)
{
      void handler(int signum);
      struct sigaction sa;

      sa.sa_handler = handler;
      sa.sa_flags   = 0;
      sigfillset(&sa.sa_mask);
      sigaction(SIGPIPE, &sa, NULL);
}



void handler(int signum)
{
      close(readsock);
      FD_CLR(readsock, &saveset);
      reqtimes[readsock].socket = NOT_USED;
      readsock++;
      siglongjmp(env, 1);
} 



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)
              if (errno == EAGAIN)
              {
                  errno = 0;
                  continue;
              }
              else raise(SIGPIPE);
         else if (nread == 0)
              raise(SIGPIPE);      /****  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)
              raise(SIGPIPE);  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}
###################################  Output  ###############################

$ s&
[1] 25351

[voyager demos]$ c
Enter string:   foo
Inside server!  Socket is 4.
Got   foo from client!
From server:   foo

Enter string: whatever
Inside server!  Socket is 4.
Got whatever from client!
From server: whatever

Enter string: 
[2]+  Stopped                 c

$ c
Enter string: foo
Inside server!  Socket is 5.
Got foo from client!
From server: foo

Enter string: bar
Inside server!  Socket is 5.
Got bar from client!
From server: bar
Enter string: quit
Inside server!  Socket is 5.

$ jobs
[1]-  Running                 s &
[2]+  Stopped                 c

$ fg %2
c
foo
Server disconnected