This is a C Program that illustrates a simple TCP (Transmission Control Protocol) server that accepts incoming client connections. Once a client connection is established, a thread is spawned to read data from the client and echo it back (if the echo option is not disabled).
You can use any C/C++ Compilers in windows to compile and run this program as it uses winsock2 windows network API.
How to Compile the TCP Client/Server program?
The following TCP Client Server program is divided into two parts, the server and the client. Please compile each program separately as per the following instructions.
Server:
To compile the server program, use the following command line. TCP server accepts incoming client connections. Once a client connection is established, a thread is spawned to read data from the client and echo it back (if the echo option is not disabled).
Compile:
cl -o Server Server.c ws2_32.lib
Command line options:
server [-p:x] [-i:IP] [-o]
-p:x Port number to listen on
-i:str Interface to listen on
-o Receive only, don’t echo the data back
Client:
This sample is the echo client. It connects to the TCP server, sends data, and reads data back from the server.
Compile:
cl -o Client Client.c ws2_32.lib
Command Line Options:
client [-p:x] [-s:IP] [-n:x] [-o]
-p:x Remote port to send to
-s:IP Server’s IP address or hostname
-n:x Number of times to send message
-o Send messages only; don’t receive
Client Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | // Module Name: Client.c // // Description: // This sample is the echo client. It connects to the TCP server, // sends data, and reads data back from the server. // // Compile: // cl -o Client Client.c ws2_32.lib // // Command Line Options: // client [-p:x] [-s:IP] [-n:x] [-o] // -p:x Remote port to send to // -s:IP Server's IP address or hostname // -n:x Number of times to send message // -o Send messages only; don't receive // #include <winsock2.h> #include <stdio.h> #include <stdlib.h> #define DEFAULT_COUNT 20 #define DEFAULT_PORT 5150 #define DEFAULT_BUFFER 2048 #define DEFAULT_MESSAGE "This is a test of the emergency \ broadcasting system" char szServer[128], // Server to connect to szMessage[1024]; // Message to send to sever int iPort = DEFAULT_PORT; // Port on server to connect to DWORD dwCount = DEFAULT_COUNT; // Number of times to send message BOOL bSendOnly = FALSE; // Send data only; don't receive // // Function: usage: // // Description: // Print usage information and exit // void usage() { printf("usage: client [-p:x] [-s:IP] [-n:x] [-o]\n\n"); printf(" -p:x Remote port to send to\n"); printf(" -s:IP Server's IP address or hostname\n"); printf(" -n:x Number of times to send message\n"); printf(" -o Send messages only; don't receive\n"); ExitProcess(1); } // // Function: ValidateArgs // // Description: // Parse the command line arguments, and set some global flags // to indicate what actions to perform // void ValidateArgs(int argc, char** argv) { int i; for (i = 1; i < argc; i++) { if ((argv[i][0] == '-') || (argv[i][0] == '/')) { switch (tolower(argv[i][1])) { case 'p': // Remote port if (strlen(argv[i]) > 3) iPort = atoi(&argv[i][3]); break; case 's': // Server if (strlen(argv[i]) > 3) strcpy(szServer, &argv[i][3]); break; case 'n': // Number of times to send message if (strlen(argv[i]) > 3) dwCount = atol(&argv[i][3]); break; case 'o': // Only send message; don't receive bSendOnly = TRUE; break; default: usage(); break; } } } } // // Function: main // // Description: // Main thread of execution. Initialize Winsock, parse the // command line arguments, create a socket, connect to the // server, and then send and receive data. // int main(int argc, char** argv) { WSADATA wsd; SOCKET sClient; char szBuffer[DEFAULT_BUFFER]; int ret, i; struct sockaddr_in server; struct hostent* host = NULL; // Parse the command line and load Winsock // ValidateArgs(argc, argv); if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("Failed to load Winsock library!\n"); return 1; } strcpy(szMessage, DEFAULT_MESSAGE); // // Create the socket, and attempt to connect to the server // sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient == INVALID_SOCKET) { printf("socket() failed: %d\n", WSAGetLastError()); return 1; } server.sin_family = AF_INET; server.sin_port = htons(iPort); server.sin_addr.s_addr = inet_addr(szServer); // // If the supplied server address wasn't in the form // "aaa.bbb.ccc.ddd" it's a hostname, so try to resolve it // if (server.sin_addr.s_addr == INADDR_NONE) { host = gethostbyname(szServer); if (host == NULL) { printf("Unable to resolve server: %s\n", szServer); return 1; } CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length); } if (connect(sClient, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { printf("connect() failed: %d\n", WSAGetLastError()); return 1; } // Send and receive data // for (i = 0; i < dwCount; i++) { ret = send(sClient, szMessage, strlen(szMessage), 0); if (ret == 0) break; else if (ret == SOCKET_ERROR) { printf("send() failed: %d\n", WSAGetLastError()); break; } printf("Send %d bytes\n", ret); if (!bSendOnly) { ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0); if (ret == 0) // Graceful close break; else if (ret == SOCKET_ERROR) { printf("recv() failed: %d\n", WSAGetLastError()); break; } szBuffer[ret] = '\0'; printf("RECV [%d bytes]: '%s'\n", ret, szBuffer); } } closesocket(sClient); WSACleanup(); return 0; } |
Server Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | // Module Name: Server.c // // Description: // This example illustrates a simple TCP server that accepts // incoming client connections. Once a client connection is // established, a thread is spawned to read data from the // client and echo it back (if the echo option is not // disabled). // // Compile: // cl -o Server Server.c ws2_32.lib // // Command line options: // server [-p:x] [-i:IP] [-o] // -p:x Port number to listen on // -i:str Interface to listen on // -o Receive only, don't echo the data back // #include <winsock2.h> #include <stdio.h> #include <stdlib.h> #define DEFAULT_PORT 5150 #define DEFAULT_BUFFER 4096 int iPort = DEFAULT_PORT; // Port to listen for clients on BOOL bInterface = FALSE, // Listen on the specified interface bRecvOnly = FALSE; // Receive data only; don't echo back char szAddress[128]; // Interface to listen for clients on // // Function: usage // // Description: // Print usage information and exit // void usage() { printf("usage: server [-p:x] [-i:IP] [-o]\n\n"); printf(" -p:x Port number to listen on\n"); printf(" -i:str Interface to listen on\n"); printf(" -o Don't echo the data back\n\n"); ExitProcess(1); } // // Function: ValidateArgs // // Description: // Parse the command line arguments, and set some global flags // to indicate what actions to perform // void ValidateArgs(int argc, char** argv) { int i; for (i = 1; i < argc; i++) { if ((argv[i][0] == '-') || (argv[i][0] == '/')) { switch (tolower(argv[i][1])) { case 'p': iPort = atoi(&argv[i][3]); break; case 'i': bInterface = TRUE; if (strlen(argv[i]) > 3) strcpy(szAddress, &argv[i][3]); break; case 'o': bRecvOnly = TRUE; break; default: usage(); break; } } } } // // Function: ClientThread // // Description: // This function is called as a thread, and it handles a given // client connection. The parameter passed in is the socket // handle returned from an accept() call. This function reads // data from the client and writes it back. // DWORD WINAPI ClientThread(LPVOID lpParam) { SOCKET sock = (SOCKET)lpParam; char szBuff[DEFAULT_BUFFER]; int ret, nLeft, idx; while (1) { // Perform a blocking recv() call // ret = recv(sock, szBuff, DEFAULT_BUFFER, 0); if (ret == 0) // Graceful close break; else if (ret == SOCKET_ERROR) { printf("recv() failed: %d\n", WSAGetLastError()); break; } szBuff[ret] = '\0'; printf("RECV: '%s'\n", szBuff); // // If we selected to echo the data back, do it // if (!bRecvOnly) { nLeft = ret; idx = 0; // // Make sure we write all the data // while (nLeft > 0) { ret = send(sock, &szBuff[idx], nLeft, 0); if (ret == 0) break; else if (ret == SOCKET_ERROR) { printf("send() failed: %d\n", WSAGetLastError()); break; } nLeft -= ret; idx += ret; } } } return 0; } // // Function: main // // Description: // Main thread of execution. Initialize Winsock, parse the // command line arguments, create the listening socket, bind // to the local address, and wait for client connections. // int main(int argc, char** argv) { WSADATA wsd; SOCKET sListen, sClient; int iAddrSize; HANDLE hThread; DWORD dwThreadId; struct sockaddr_in local, client; ValidateArgs(argc, argv); if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("Failed to load Winsock!\n"); return 1; } // Create our listening socket // sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sListen == SOCKET_ERROR) { printf("socket() failed: %d\n", WSAGetLastError()); return 1; } // Select the local interface and bind to it // if (bInterface) { local.sin_addr.s_addr = inet_addr(szAddress); if (local.sin_addr.s_addr == INADDR_NONE) usage(); } else local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(iPort); if (bind(sListen, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR) { printf("bind() failed: %d\n", WSAGetLastError()); return 1; } listen(sListen, 8); // // In a continous loop, wait for incoming clients. Once one // is detected, create a thread and pass the handle off to it. // while (1) { iAddrSize = sizeof(client); sClient = accept(sListen, (struct sockaddr*)&client, &iAddrSize); if (sClient == INVALID_SOCKET) { printf("accept() failed: %d\n", WSAGetLastError()); break; } printf("Accepted client: %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThreadId); if (hThread == NULL) { printf("CreateThread() failed: %d\n", GetLastError()); break; } CloseHandle(hThread); } closesocket(sListen); WSACleanup(); return 0; } |