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