| 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; |