Sender Program (sender.c):
The sender program is a UDP datagram sender that can be configured through command line options. It initializes Winsock, creates a UDP socket, and either connects to a recipient’s IP address or uses sendto()
to send datagram messages. The program allows customization of parameters such as the remote port, recipient’s IP address, message count, buffer size, and the character used to fill the buffer.
Compile:
cl -o Sender Sender.c ws2_32.lib
Command line options:
sender [-p:int] [-r:IP] [-c] [-n:x] [-b:x] [-d:c]
-p:int Remote port
-r:IP Recipient’s IP address or hostname
-c Connect to remote IP first
-n:x Number of times to send message
-b:x Size of buffer to send
-d:c Character to fill buffer with
Receiver Program (receiver.c):
The receiver program complements the sender by receiving UDP datagrams. It initializes Winsock, creates a UDP socket, binds to a specified local IP and port, and enters a loop to continuously receive datagram messages using recvfrom()
. The program supports command line options for configuring the local port, local IP address, and buffer size. Received data can be processed within the loop, making it suitable for handling incoming UDP messages.
Compile:
cl -o Receiver Receiver.c ws2_32.lib
Command line options:
sender [-p:int] [-i:IP][-n:x] [-b:x]
-p:int Local port
-i:IP Local IP address to listen on
-n:x Number of times to send message
-b:x Size of buffer to send
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 | // Module Name: Sender.c // // Description: // This sample sends UDP datagrams to the specified recipient. // The -c option first calls connect() to associate the // recipient's IP address with the socket handle so that the // send() function can be used as opposed to the sendto() call. // // Compile: // cl -o Sender Sender.c ws2_32.lib // // Command line options: // sender [-p:int] [-r:IP] [-c] [-n:x] [-b:x] [-d:c] // -p:int Remote port // -r:IP Recipient's IP address or hostname // -c Connect to remote IP first // -n:x Number of times to send message // -b:x Size of buffer to send // -d:c Character to fill buffer with // #include <winsock2.h> #include <stdio.h> #include <stdlib.h> #define DEFAULT_PORT 5150 #define DEFAULT_COUNT 25 #define DEFAULT_CHAR 'a' #define DEFAULT_BUFFER_LENGTH 64 BOOL bConnect = FALSE; // Connect to recipient first int iPort = DEFAULT_PORT; // Port to send data to char cChar = DEFAULT_CHAR; // Character to fill buffer DWORD dwCount = DEFAULT_COUNT, // Number of messages to send dwLength = DEFAULT_BUFFER_LENGTH; // Length of buffer to send char szRecipient[128]; // Recipient's IP or hostname // // Function: usage // // Description: // Print usage information and exit // void usage() { printf("usage: sender [-p:int] [-r:IP] " "[-c] [-n:x] [-b:x] [-d:c]\n\n"); printf(" -p:int Remote port\n"); printf(" -r:IP Recipients IP address or hostname\n"); printf(" -c Connect to remote IP first\n"); printf(" -n:x Number of times to send message\n"); printf(" -b:x Size of buffer to send\n"); printf(" -d:c Character to fill buffer with\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': // Remote port if (strlen(argv[i]) > 3) iPort = atoi(&argv[i][3]); break; case 'r': // Recipient's IP addr if (strlen(argv[i]) > 3) strcpy(szRecipient, &argv[i][3]); break; case 'c': // Connect to recipients IP addr bConnect = TRUE; break; case 'n': // Number of times to send message if (strlen(argv[i]) > 3) dwCount = atol(&argv[i][3]); break; case 'b': // Buffer size if (strlen(argv[i]) > 3) dwLength = atol(&argv[i][3]); break; case 'd': // Character to fill buffer cChar = argv[i][3]; break; default: usage(); break; } } } } // // Function: main // // Description: // Main thread of execution. Initialize Winsock, parse the command // line arguments, create a socket, connect to the remote IP // address if specified, and then send datagram messages to the // recipient. // int main(int argc, char **argv) { WSADATA wsd; SOCKET s; char *sendbuf = NULL; int ret, i; SOCKADDR_IN recipient; // Parse the command line and load Winsock // ValidateArgs(argc, argv); if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup failed!\n"); return 1; } // Create the socket // s = socket(AF_INET, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { printf("socket() failed; %d\n", WSAGetLastError()); return 1; } // Resolve the recipient's IP address or hostname // recipient.sin_family = AF_INET; recipient.sin_port = htons((short)iPort); if ((recipient.sin_addr.s_addr = inet_addr(szRecipient)) == INADDR_NONE) { struct hostent *host=NULL; host = gethostbyname(szRecipient); if (host) CopyMemory(&recipient.sin_addr, host->h_addr_list[0], host->h_length); else { printf("gethostbyname() failed: %d\n", WSAGetLastError()); WSACleanup(); return 1; } } // Allocate the send buffer // sendbuf = GlobalAlloc(GMEM_FIXED, dwLength); if (!sendbuf) { printf("GlobalAlloc() failed: %d\n", GetLastError()); return 1; } memset(sendbuf, cChar, dwLength); // // If the connect option is set, "connect" to the recipient // and send the data with the send() function // if (bConnect) { if (connect(s, (SOCKADDR *)&recipient, sizeof(recipient)) == SOCKET_ERROR) { printf("connect() failed: %d\n", WSAGetLastError()); GlobalFree(sendbuf); WSACleanup(); return 1; } for(i = 0; i < dwCount; i++) { ret = send(s, sendbuf, dwLength, 0); if (ret == SOCKET_ERROR) { printf("send() failed: %d\n", WSAGetLastError()); break; } else if (ret == 0) break; // send() succeeded! } } else { // Otherwise, use the sendto() function // for(i = 0; i < dwCount; i++) { ret = sendto(s, sendbuf, dwLength, 0, (SOCKADDR *)&recipient, sizeof(recipient)); if (ret == SOCKET_ERROR) { printf("sendto() failed; %d\n", WSAGetLastError()); break; } else if (ret == 0) break; // sendto() succeeded! } } closesocket(s); GlobalFree(sendbuf); WSACleanup(); return 0; } |
Here is a basic example of a receiver.c program that complements the sender.c program. This receiver program binds to the specified interface and port number and then blocks on a recvfrom()
call to receive UDP datagrams:
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 | // Module Name: Receiver.c // // Description: // This sample receives UDP datagrams by binding to // the specified interface and port number and then blocking on a recvfrom() // call // // Compile: // cl -o Receiver Receiver.c ws2_32.lib // // Command line options: // receiver [-p:int] [-i:IP] [-b:x] // -p:int Local port // -i:IP Local IP address to listen on // -b:x Size of buffer to receive // #include <winsock2.h> #include <stdio.h> #include <stdlib.h> #define DEFAULT_PORT 5150 #define DEFAULT_BUFFER_LENGTH 64 int iPort = DEFAULT_PORT; // Port to receive data on DWORD dwLength = DEFAULT_BUFFER_LENGTH; // Length of buffer to receive // // Function: usage // // Description: // Print usage information and exit // void usage() { printf("usage: receiver [-p:int] [-i:IP] [-b:x]\n\n"); printf(" -p:int Local port\n"); printf(" -i:IP Local IP address to listen on\n"); printf(" -b:x Size of buffer to receive\n\n"); ExitProcess(1); } // // Function: ValidateArgs // // Description: // Parse the command line arguments and set the global variables // 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': // Local port if (strlen(argv[i]) > 3) iPort = atoi(&argv[i][3]); break; case 'i': // Local IP addr if (strlen(argv[i]) > 3) ; // You can add code here to handle the IP address if needed break; case 'b': // Buffer size if (strlen(argv[i]) > 3) dwLength = atol(&argv[i][3]); break; default: usage(); break; } } } } // // Function: main // // Description: // Main thread of execution. Initialize Winsock, parse the command // line arguments, create a socket, bind to the local IP and port, // and then receive datagram messages. // int main(int argc, char **argv) { WSADATA wsd; SOCKET s; char *recvbuf = NULL; int ret; SOCKADDR_IN local; SOCKADDR_IN sender; int senderSize; // Parse the command line and load Winsock ValidateArgs(argc, argv); if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup failed!\n"); return 1; } // Create the socket s = socket(AF_INET, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { printf("socket() failed; %d\n", WSAGetLastError()); return 1; } // Bind to the local IP and port local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; local.sin_port = htons((short)iPort); if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR) { printf("bind() failed: %d\n", WSAGetLastError()); closesocket(s); WSACleanup(); return 1; } // Allocate the receive buffer recvbuf = (char *)malloc(dwLength); if (!recvbuf) { printf("malloc() failed!\n"); closesocket(s); WSACleanup(); return 1; } while (1) { senderSize = sizeof(sender); // Receive data ret = recvfrom(s, recvbuf, dwLength, 0, (SOCKADDR *)&sender, &senderSize); if (ret == SOCKET_ERROR) { printf("recvfrom() failed; %d\n", WSAGetLastError()); break; } printf("Received %d bytes from %s:%d\n", ret, inet_ntoa(sender.sin_addr), ntohs(sender.sin_port)); // You can process the received data here } closesocket(s); free(recvbuf); WSACleanup(); return 0; } |