
/* a single process concurrent server using select */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#define BUFSIZE 1024

int echo(int), SetupSocket();
void error(char *);

int main(int argc, char *argv[])
{
     struct sockaddr_in from;
     int msock;       /* master socket */
     fd_set rfds;     /* read file descriptors */
     fd_set afds;     /* active fds */
     int    alen;
     int fd, nfds, n;

     msock = SetupSocket(); 

     FD_ZERO(&afds);
     FD_SET(msock,&afds);
     nfds = 4;  /* number of open file descriptors plus 1 */
     while (1) {        
        memcpy((char *)&rfds, (char *)&afds,  sizeof(rfds));
        n = select(nfds,&rfds,NULL, NULL, NULL);
        if (n < 0) error("select");
        if (FD_ISSET(msock, &rfds)) {
             int ssock;
             alen = sizeof(from);
             ssock = accept(msock, (struct sockaddr *)
                     &from,&alen);
             if (ssock < 0) error("accept");
             printf("Accepted a connection, the new socket is %d\n",ssock);
             FD_SET(ssock,&afds);
             nfds++;
        }
        for (fd = 0;fd<nfds;++fd)
	  if (fd != msock && FD_ISSET(fd, &rfds)) {
	    printf ("The message is on socket %d\n",fd);
                 if (echo(fd) == 0) {
                    close(fd);
                    FD_CLR(fd, &afds);
                 }
	  }
      } /* end of while */
}

/*** echo() ************/
int echo(int fd)
{
   char buf[BUFSIZE]; 
   int n;
   n = read(fd,buf,BUFSIZE);
   if (n < 0) error("read");
   if (n == 0) return 0;
   if (write(1,buf,n) < 0)  error("writing");
   if (write(1,"\n",1) < 0) error("writing");;
   if (write(fd,buf,n) < 0) error("writing");
   return n;
}

void error(char *msg)
{
    perror(msg);
    exit(0);
}

/* SetUpSocket() ***
creates a server socket
*/
int SetupSocket()
{
    int sockfd, len;
    struct sockaddr_in server;  

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
       error("socket");
    server.sin_family=AF_INET;
    server.sin_addr.s_addr=INADDR_ANY;
    server.sin_port=htons(51718);  
    len=sizeof server;
    if (bind(sockfd,(struct sockaddr *)&server,len) < 0) 
        error("binding socket");
    if (listen(sockfd,5)<0)
        error("listen");
    return sockfd;
}

