1 /**************************************************
  2  * MULTIECHO SERVER                               *
  3  *                                                *
  4  * NO LICENSE, THIS CODE IS PUBLIC DOMAIN         *
  5  *                                                *
  6  * Written by Pioz                                *
  7  * To compile: "gcc -o server server.c -lpthread" *
  8  **************************************************/
  9 
 10 #include <stdio.h>      /* For printf() and fprintf() */
 11 #include <sys/socket.h> /* For socket(), bind(), connect(), send() and recv() */
 12 #include <arpa/inet.h>  /* For sockaddr_in and inet_ntoa() */
 13 #include <stdlib.h>     /* For atoi() and exit() */
 14 #include <string.h>     /* For memset() */
 15 #include <unistd.h>     /* For close() */
 16 #include <pthread.h>    /* For pthread */
 17 
 18 #define BUFSIZE 256     /* Size of string to send */
 19 #define MAXCLIENT 4     /* Max client to echoing */
 20 
 21 void  dieWithError(char* errorMessage);           /* Error handling function */
 22 int   createTCPServerSocket(unsigned short port); /* Create a server socket */
 23 int   acceptTCPConnection(int servSock);          /* Accept TCP connection request */
 24 void* child(void* arg);                           /* Body of child process */
 25 
 26 pthread_mutex_t mutx = PTHREAD_MUTEX_INITIALIZER; /* Mutexes must be shared as well */
 27 int allSock[MAXCLIENT] = {-1,-1,-1,-1};           /* Socket descriptor for all client */
 28 
 29 typedef struct data {
 30   int field1;
 31   char field2[BUFSIZE];
 32 } data_t;
 33 
 34 int main(int argc, char* argv[])
 35 {
 36   int servSock;        /* Socket descriptor for server */
 37   int sock;            /* Socket descriptor for client */
 38   unsigned short port; /* Server port */
 39   int current = 0;     /* Current socket index */
 40   pthread_t pchild;    /* Pointer to child process */
 41 
 42   if (argc != 2) /* Test for correct number of arguments */
 43     {
 44       fprintf(stderr, "Usage:  %s <Server port>\n", argv[0]);
 45       exit(1);
 46     }
 47 
 48   port = atoi(argv[1]); /* First arg: local port */
 49 
 50   /* Create the server socket */
 51   servSock = createTCPServerSocket(port);
 52 
 53   for (;;) /* run forever... nearly */
 54     {
 55       if (current < MAXCLIENT)
 56         {
 57           sock = acceptTCPConnection(servSock);
 58           pthread_mutex_lock(&mutx); /* r/w shared resources */
 59           allSock[current] = sock;
 60           int index = current;
 61           current++;
 62           pthread_mutex_unlock(&mutx);
 63 
 64           if (pthread_create(&pchild, 0, child, &index) != 0)
 65             dieWithError("pthread_create() failed");      
 66         }
 67       else
 68         break;
 69     }
 70   close(servSock);         /* Close server socket */
 71   pthread_join(pchild, 0); /* Wait for the child to finish */
 72 }
 73 
 74 ///////////////////////////////////////////////////////////////////////////////////
 75 
 76 void* child(void* arg)
 77 {
 78   pthread_mutex_lock(&mutx);              /* r/w shared resources */
 79   int index = *((int*)arg);               /* Index of current socket */
 80   int sock = allSock[index];              /* Descriptor for current socket */
 81   pthread_mutex_unlock(&mutx);
 82   data_t data;                            /* The data in the network */
 83   unsigned int dataSize = sizeof(data_t); /* Bytes to send and receive */
 84   int recvMsgSize;                        /* Size of received message */
 85 
 86   if ((recvMsgSize = recv(sock, &data, dataSize, 0)) < 0)
 87     dieWithError("recv() failed");
 88   
 89   /* Send received data to all connected client and receive again until end of transmission */
 90   while (recvMsgSize > 0) /* Zero indicates end of transmission */
 91     {
 92       int i;
 93       for(i = 0; i < MAXCLIENT; i++) /* Send buffer data to all client */
 94         {
 95 	       pthread_mutex_lock(&mutx); /* r/w shared resources */
 96 	       if (allSock[i] != -1)      /* If file descriptor is -1 there are not a client associated */
 97 	         if(send(allSock[i], &data, recvMsgSize, 0) != recvMsgSize)
 98 	           dieWithError("send() failed");
 99 	       pthread_mutex_unlock(&mutx);
100 	     }
101       /* See if there is more data to receive */
102       if ((recvMsgSize = recv(sock, &data, dataSize, 0)) < 0)
103       	dieWithError("recv() failed");
104     }
105   pthread_mutex_lock(&mutx); /* r/w shared resources */
106   close(allSock[index]);     /* Close client socket */
107   allSock[index] = -1;       /* Reset the socket container */
108   pthread_mutex_unlock(&mutx);
109 }
110 
111 ///////////////////////////////////////////////////////////////////////////////////
112 
113 void dieWithError(char* errorMessage)
114 {
115   perror(errorMessage);
116   exit(1);
117 }
118 
119 ///////////////////////////////////////////////////////////////////////////////////
120 
121 int acceptTCPConnection(int servSock)
122 {
123   int clntSock;                /* Socket descriptor for client */
124   struct sockaddr_in clntAddr; /* Client address */
125   unsigned int clntLen;        /* Length of client address data structure */
126 
127   /* Set the size of the in-out parameter */
128   clntLen = sizeof(clntAddr);
129   
130   /* Wait for a client to connect */
131   if ((clntSock = accept(servSock, (struct sockaddr*)&clntAddr, &clntLen)) < 0)
132     dieWithError("accept() failed");
133     
134   /* clntSock is connected to a client! */
135   printf("Handling client %s\n", inet_ntoa(clntAddr.sin_addr));
136 
137   return clntSock;
138 }
139 
140 ///////////////////////////////////////////////////////////////////////////////////
141 
142 int createTCPServerSocket(unsigned short port)
143 {
144   int sock;                    /* Socket to create */
145   struct sockaddr_in servAddr; /* Local address */
146   
147   /* Create socket for incoming connections */
148   if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
149     dieWithError("socket() failed");
150   
151   /* Construct local address structure */
152   memset(&servAddr, 0, sizeof(servAddr));       /* Zero out structure */
153   servAddr.sin_family = AF_INET;                /* Internet address family */
154   servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
155   servAddr.sin_port = htons(port);              /* Local port */
156   
157   /* Bind to the local address */
158   if (bind(sock, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0)
159     dieWithError("bind() failed");
160   
161   /* Mark the socket so it will listen for incoming connections */
162   if (listen(sock, MAXCLIENT) < 0)
163     dieWithError("listen() failed");
164 
165   return sock;
166 }

Download | Top | Back | Home


Maintained by Pioz