149 | | int i; |
150 | | int client_s; |
151 | | struct sockaddr_in addr; |
152 | | socklen_t socklen = sizeof(addr); |
153 | | |
154 | | // Check for new client connections |
155 | | client_s = accept(server_s, (sockaddr*)&addr, &socklen); |
156 | | if(client_s >= 0) |
157 | | { |
158 | | char szIP[INET_ADDRSTRLEN]; |
159 | | |
160 | | inet_ntop(AF_INET, &addr.sin_addr, szIP, INET_ADDRSTRLEN); |
161 | | |
162 | | printf("TCP/IP server connection from %s socket %d\r\n", szIP, client_s); |
163 | | |
164 | | /* nonblocking socket */ |
165 | | if (fcntl(client_s, F_SETFL, O_NONBLOCK) == -1) |
166 | | { |
167 | | printf("fcntl: unable to set new socket to non-block\r\n"); |
168 | | close(client_s); |
169 | | } |
170 | | else |
171 | | { |
172 | | client_list.push_back(client_s); |
173 | | } |
174 | | } |
175 | | |
176 | | if(client_list.size() > 0) |
177 | | { |
178 | | fd_set rfds; |
179 | | FD_ZERO(&rfds); |
180 | | int nMaxfd = 0; |
181 | | for(i = 0; i < (int)client_list.size(); i++) |
182 | | { |
183 | | FD_SET(client_list[i], &rfds); |
184 | | if(client_list[i] > nMaxfd) |
185 | | nMaxfd = client_list[i]; |
186 | | } |
187 | | |
188 | | struct timeval tv; |
189 | | tv.tv_sec = 0; |
190 | | tv.tv_usec = 0; |
191 | | |
192 | | int retval = select(nMaxfd + 1, &rfds, NULL, NULL, &tv); |
193 | | if(retval == -1) |
194 | | printf("select return -1\r\n"); |
195 | | else if(retval > 0) |
196 | | { |
197 | | printf("select returned %d\r\n", retval); |
198 | | |
199 | | int rcvlen; |
200 | | char data[20], sendbuf[50]; |
201 | | int z; |
202 | | int remove = -1; |
203 | | |
204 | | // Process all connected clients |
205 | | for(i = 0; i < (int)client_list.size(); i++) |
206 | | { |
207 | | if(FD_ISSET(client_list[i], &rfds)) |
208 | | { |
209 | | rcvlen = recv(client_list[i], data, sizeof(data), 0); |
210 | | for(z = 0; z < rcvlen; z++) |
211 | | { |
212 | | if(data[z] == 0x05) // ENQ = CTRL-E received |
213 | | { |
214 | | // Send response to client |
215 | | time_t rawtime; |
216 | | struct tm *timeinfo; |
217 | | time(&rawtime); |
218 | | timeinfo = localtime(&rawtime); |
219 | | |
220 | | sprintf(sendbuf, "Server time is: %02d:%02d:%02d ", |
221 | | timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); |
222 | | |
223 | | send(client_list[i], sendbuf, strlen(sendbuf), 0); |
224 | | } |
225 | | } |
226 | | if(rcvlen <= 0) |
227 | | { |
228 | | printf("recv Error %d\r\n", rcvlen); |
229 | | remove = i; |
230 | | } |
231 | | } |
232 | | } |
233 | | if(remove >= 0) |
234 | | { |
235 | | printf("Removing %d client socket %d\r\n", remove, client_list[remove]); |
236 | | client_list.erase(client_list.begin() + remove); |
237 | | } |
238 | | } |
239 | | } |
240 | | return 0; |
| 153 | int i; |
| 154 | int client_s; |
| 155 | struct sockaddr_in addr; |
| 156 | socklen_t socklen = sizeof(addr); |
| 157 | |
| 158 | // Check for new client connections |
| 159 | client_s = accept(server_s, (sockaddr*)&addr, &socklen); |
| 160 | if(client_s >= 0) |
| 161 | { |
| 162 | char szIP[INET_ADDRSTRLEN]; |
| 163 | inet_ntop(AF_INET, &addr.sin_addr, szIP, INET_ADDRSTRLEN); |
| 164 | |
| 165 | printf("TCP/IP server connection from IP %s socket %d\r\n", szIP, client_s); |
| 166 | |
| 167 | /* nonblocking socket */ |
| 168 | if(fcntl(client_s, F_SETFL, O_NONBLOCK) == -1) |
| 169 | { |
| 170 | printf("fcntl: unable to set new socket to non-block\r\n"); |
| 171 | close(client_s); |
| 172 | } |
| 173 | else |
| 174 | { |
| 175 | // Add client information to list of connected clients |
| 176 | client_info info; |
| 177 | info.socket = client_s; |
| 178 | info.pos = 0; |
| 179 | client_list.push_back(info); |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | // Service any connected clients |
| 184 | if(client_list.size() > 0) |
| 185 | { |
| 186 | struct timeval tv; |
| 187 | tv.tv_sec = 0; |
| 188 | tv.tv_usec = 0; |
| 189 | |
| 190 | // Load up structure for "select" statement to check for receive data from all connected clients |
| 191 | fd_set rfds; |
| 192 | FD_ZERO(&rfds); |
| 193 | int nMaxfd = 0; |
| 194 | for(i = 0; i < (int)client_list.size(); i++) |
| 195 | { |
| 196 | FD_SET(client_list[i].socket, &rfds); |
| 197 | if(client_list[i].socket > nMaxfd) |
| 198 | nMaxfd = client_list[i].socket; |
| 199 | } |
| 200 | |
| 201 | int retval = select(nMaxfd + 1, &rfds, NULL, NULL, &tv); |
| 202 | if(retval == -1) |
| 203 | { |
| 204 | printf("select return -1\r\n"); |
| 205 | } |
| 206 | else if(retval > 0) |
| 207 | { |
| 208 | int rcvlen; |
| 209 | char data[20], sendbuf[50]; |
| 210 | int z; |
| 211 | int remove = -1; |
| 212 | |
| 213 | // Loop through array of all connected clients |
| 214 | for(i = 0; i < (int)client_list.size(); i++) |
| 215 | { |
| 216 | // Select statement will have loaded rfds to identify which clients have data available to read from |
| 217 | if(FD_ISSET(client_list[i].socket, &rfds)) |
| 218 | { |
| 219 | rcvlen = recv(client_list[i].socket, data, sizeof(data), 0); |
| 220 | // Loop through bytes received from this client |
| 221 | for(z = 0; z < rcvlen; z++) |
| 222 | { |
| 223 | // If ENTER we have completed message - otherwise add character to the client read buffer |
| 224 | if(data[z] == '\r') |
| 225 | { |
| 226 | // Must terminate the string |
| 227 | client_list[i].buf[client_list[i].pos] = '\0'; |
| 228 | printf("Socket %d message [%s]\r\n", client_list[i].socket, client_list[i].buf); |
| 229 | |
| 230 | // In this sample we check for "TIME<CR>" received and respond with the server time |
| 231 | if(!strcmp(client_list[i].buf, "TIME")) |
| 232 | { |
| 233 | // Get current time |
| 234 | time_t rawtime; |
| 235 | struct tm *timeinfo; |
| 236 | time(&rawtime); |
| 237 | timeinfo = localtime(&rawtime); |
| 238 | |
| 239 | // Format time into string |
| 240 | sprintf(sendbuf, "Server time is: %02d:%02d:%02d ", |
| 241 | timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); |
| 242 | |
| 243 | // Send to client |
| 244 | send(client_list[i].socket, sendbuf, strlen(sendbuf), 0); |
| 245 | } |
| 246 | |
| 247 | // Reset the buffer position for the next request |
| 248 | client_list[i].pos = 0; |
| 249 | } |
| 250 | else |
| 251 | { |
| 252 | // Add character to buffer |
| 253 | client_list[i].buf[client_list[i].pos++] = data[z]; |
| 254 | |
| 255 | // In case of overflow reset position to prevent overwriting memory and crashing |
| 256 | if(client_list[i].pos >= BUFSIZE) |
| 257 | client_list[i].pos = 0; |
| 258 | } |
| 259 | } |
| 260 | if(rcvlen <= 0) |
| 261 | { |
| 262 | // If the receive length is zero or negative indicates an error - we lost the connection |
| 263 | // Set variable remove to indicate this client should be removed |
| 264 | printf("recv Error %d\r\n", rcvlen); |
| 265 | remove = i; |
| 266 | } |
| 267 | } |
| 268 | } |
| 269 | if(remove >= 0) |
| 270 | { |
| 271 | // If a client disconnected remove it from the list |
| 272 | printf("Removing %d client socket %d\r\n", remove, client_list[remove].socket); |
| 273 | client_list.erase(client_list.begin() + remove); |
| 274 | } |
| 275 | } |
| 276 | } |
| 277 | return 0; |
245 | | |
246 | | server_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
247 | | if(server_s == -1) |
248 | | { |
249 | | printf("unable to create socket\r\n"); |
250 | | return -1; |
251 | | } |
252 | | |
253 | | /* server socket is nonblocking */ |
254 | | if (fcntl(server_s, F_SETFL, O_NONBLOCK) == -1) |
255 | | { |
256 | | printf("fcntl: unable to set server socket to nonblocking"); |
257 | | return -1; |
258 | | } |
259 | | |
260 | | // /* close server socket on exec so CGIs can't write to it */ |
261 | | // if (fcntl(server_s, F_SETFD, 1) == -1) { |
262 | | // printf("can't set close-on-exec on server socket!"); |
263 | | // } |
264 | | |
265 | | /* reuse socket addr */ |
266 | | if ((setsockopt(server_s, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof (sock_opt))) == -1) |
267 | | { |
268 | | printf("setsockopt"); |
269 | | } |
270 | | |
271 | | |
272 | | struct sockaddr_in server_sockaddr; |
273 | | memset(&server_sockaddr, 0, sizeof server_sockaddr); |
274 | | server_sockaddr.sin_family = PF_INET; |
275 | | |
276 | | server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
277 | | |
278 | | server_sockaddr.sin_port = htons(nPort); |
279 | | |
280 | | if(bind(server_s, (struct sockaddr *) &server_sockaddr, sizeof (server_sockaddr)) == -1) |
281 | | { |
282 | | printf("Unable to bind\r\n"); |
283 | | return -1; |
284 | | } |
285 | | |
286 | | if(listen(server_s, 10) == -1) |
287 | | { |
288 | | printf("unable to listen"); |
289 | | } |
290 | | |
291 | | while(1) |
292 | | { |
293 | | ServerProcess(); |
294 | | } |
295 | | |
296 | | return 0; |
| 282 | // Create the server socket |
| 283 | server_s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 284 | if(server_s == -1) |
| 285 | { |
| 286 | printf("unable to create socket\r\n"); |
| 287 | return -1; |
| 288 | } |
| 289 | |
| 290 | // Set server socket to be nonblocking |
| 291 | if(fcntl(server_s, F_SETFL, O_NONBLOCK) == -1) |
| 292 | { |
| 293 | printf("fcntl: unable to set server socket to nonblocking"); |
| 294 | return -1; |
| 295 | } |
| 296 | |
| 297 | // Set server to reuse socket addresses |
| 298 | if((setsockopt(server_s, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof (sock_opt))) == -1) |
| 299 | { |
| 300 | printf("setsockopt"); |
| 301 | } |
| 302 | |
| 303 | // Prepare sockaddr structure before binding |
| 304 | struct sockaddr_in server_sockaddr; |
| 305 | memset(&server_sockaddr, 0, sizeof server_sockaddr); |
| 306 | server_sockaddr.sin_family = PF_INET; |
| 307 | server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); |
| 308 | server_sockaddr.sin_port = htons(nPort); |
| 309 | |
| 310 | // Bind the socket address |
| 311 | if(bind(server_s, (struct sockaddr *) &server_sockaddr, sizeof (server_sockaddr)) == -1) |
| 312 | { |
| 313 | printf("Unable to bind\r\n"); |
| 314 | return -1; |
| 315 | } |
| 316 | |
| 317 | // Begin listening for clients to connect |
| 318 | if(listen(server_s, 10) == -1) |
| 319 | { |
| 320 | printf("unable to listen"); |
| 321 | } |
| 322 | |
| 323 | struct timespec delaytm; |
| 324 | delaytm.tv_sec = 0; |
| 325 | delaytm.tv_nsec = 8000000; |
| 326 | |
| 327 | // Processing loop |
| 328 | while(1) |
| 329 | { |
| 330 | ServerProcess(); |
| 331 | |
| 332 | // Small time delay to help OS perform its processing at a smooth rate |
| 333 | nanosleep(&delaytm, NULL); |
| 334 | } |
| 335 | |
| 336 | return 0; |