106 | | // TCP/IP Server Example |
| 106 | //============================================================================ |
| 107 | // Name : tcpip_server.cpp |
| 108 | // Author : Don Wilson |
| 109 | // Version : |
| 110 | // Copyright : Cardinal Scale Mfg |
| 111 | // Description : TCP/IP Server Demo |
| 112 | //============================================================================ |
| 113 | |
| 114 | #include <stdio.h> |
| 115 | #include <stdlib.h> |
| 116 | #include <unistd.h> |
| 117 | #include <termios.h> |
| 118 | #include <fcntl.h> |
| 119 | |
| 120 | #include <string.h> |
| 121 | |
| 122 | #include <math.h> |
| 123 | #include <time.h> |
| 124 | |
| 125 | #include <signal.h> |
| 126 | |
| 127 | #include <netinet/in.h> |
| 128 | #include <arpa/inet.h> |
| 129 | |
| 130 | #include <sys/mman.h> |
| 131 | #include <sys/types.h> /* socket, bind, accept */ |
| 132 | #include <sys/socket.h> /* socket, bind, accept, setsockopt, */ |
| 133 | #include <sys/stat.h> /* open */ |
| 134 | |
| 135 | #include <vector> |
| 136 | using namespace std; |
| 137 | |
| 138 | // Dynamic list to keep track of connected clients |
| 139 | vector<int> client_list; |
| 140 | |
| 141 | int server_s; |
| 142 | |
| 143 | const int sock_opt = 1; |
| 144 | |
| 145 | const int nPort = 10010; // Change to use a different TCP/IP port |
| 146 | |
| 147 | int ServerProcess(void) |
| 148 | { |
| 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; |
| 241 | } |
| 242 | |
| 243 | int main() |
| 244 | { |
| 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; |
| 297 | } |
| 298 | |