// // A simple Internet server application. // It listens to the port written in command line (default 1234), // and accepts connections. For each connection it starts a separate // thread that receives messages from a client, inverts them and // sends them back (i.e. the server acts as "Inverse echo"). // // Usage: // server [port_to_listen] // Default is the port 1234. // #include #include #include #include static void usage(); static void invertString(char* str); // Receiving thread body function static DWORD WINAPI receiveMessages(void* arg); int main(int argc, char *argv[]) { if (argc > 1 && *(argv[1]) == '-') { usage(); exit(1); } // Initialize Winsock DLL WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; int err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { printf("WSAStartup failed with error: %d\n", err); exit(-1); } int listenPort = 1234; if (argc > 1) listenPort = atoi(argv[1]); // Create a socket int s0 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s0 < 0) { perror("Cannot create a socket"); exit(1); } // Fill in the address structure containing self address struct sockaddr_in myaddr; memset(&myaddr, 0, sizeof(struct sockaddr_in)); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(listenPort); // Port to listen myaddr.sin_addr.s_addr = htonl(INADDR_ANY); // Bind a socket to the address int res = bind(s0, (struct sockaddr*) &myaddr, sizeof(myaddr)); if (res < 0) { printf( "Cannot bind a socket: err=%d\n", WSAGetLastError() ); exit(1); } // Set the "LINGER" timeout to zero, to close the listen socket // immediately at program termination. struct linger linger_opt = { 1, 0 }; // Linger active, timeout 0 setsockopt( s0, SOL_SOCKET, SO_LINGER, (const char*) &linger_opt, sizeof(linger_opt) ); // Now, listen for a connection res = listen(s0, 5); // "1" is the maximal length of the queue if (res < 0) { printf( "Cannot listen: err=%d\n", WSAGetLastError() ); exit(1); } while (true) { // Accept a connection (the "accept" command waits for a connection with // no timeout limit...) struct sockaddr_in peeraddr; int peeraddr_len = sizeof(peeraddr); int s1 = accept(s0, (struct sockaddr*) &peeraddr, &peeraddr_len); if (s1 < 0) { printf( "Cannot accept: err=%d\n", WSAGetLastError() ); exit(1); } // A connection is accepted. The new socket "s1" is created // for data input/output. The peeraddr structure is filled in with // the address of connected entity, print it. printf( "Connection from IP %d.%d.%d.%d, port %d\n", (int)(ntohl(peeraddr.sin_addr.s_addr) >> 24) & 0xff, // High byte of address (int)(ntohl(peeraddr.sin_addr.s_addr) >> 16) & 0xff, // . . . (int)(ntohl(peeraddr.sin_addr.s_addr) >> 8) & 0xff, // . . . (int)ntohl(peeraddr.sin_addr.s_addr) & 0xff, // Low byte of addr (int)ntohs(peeraddr.sin_port) ); fflush(stdout); int *sock1 = new int(s1); // Create a receiving thread HANDLE hReceivingThread = NULL; DWORD receivingThreadID = 0; hReceivingThread = CreateThread( NULL, // lpThreadAttributes 0, // dwStackSize - default &receiveMessages, // thread starting function (void *) sock1, // parameter of thread starting function 0, // dwCreationFlags &receivingThreadID ); if (hReceivingThread == NULL) { printf( "Cannot create receiving thread: error %d\n", (int) GetLastError() ); exit(-1); } CloseHandle(hReceivingThread); // Continue listening... } // end while closesocket(s0); // Close the data socket WSACleanup(); return 0; } static void usage() { printf( "A simple Internet server application.\n" "It listens to the port given in a command line (default 1234)\n" "and accepts connections. For each connection it starts a separate\n" "thread that receives messages from a client, inverts them and\n" "sends them back (i.e. the server acts as \"Inverse echo\").\n\n" "Usage:\n" " server [port_to_listen]\n" "Default is the port 1234.\n" ); } static DWORD WINAPI receiveMessages(void* arg) { // printf("Receiving thread is started.\n"); // fflush(stdout); int* sock = (int *) arg; int s = *sock; delete sock; char receiveBuffer[1024]; while (true) { int res = recv(s, receiveBuffer, 1020, 0); if (res <= 0) { closesocket(s); break; } receiveBuffer[res] = 0; // Remove "\r\n" at the end of line if (receiveBuffer[res-1] == '\n') { --res; receiveBuffer[res] = 0; } if (res > 0 && receiveBuffer[res-1] == '\r') { --res; receiveBuffer[res] = 0; } printf("%s\n", receiveBuffer); fflush(stdout); invertString(receiveBuffer); strcat(receiveBuffer, "\r\n"); res += 2; // Send the inverted line back to client res = send(s, receiveBuffer, res, 0); if (res < 0) { closesocket(s); break; } } // end while return 0; } static void invertString(char* str) { int len = (int) strlen(str); int i = 0; int j = len-1; while (i < j) { char c = str[i]; str[i] = str[j]; str[j] = c; ++i; --j; } }