UDP Sender and Receiver

Sender: 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

Receiver: 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:
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

/*******************************************************
*     MYCPLUS Sample Code - http://www.mycplus.com     *
*                                                     *
*   This code is made available as a service to our   *
*      visitors and is provided strictly for the      *
*               purpose of illustration.              *
*                                                     *
* Please direct all inquiries to saqib at mycplus.com *
*******************************************************/

// 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 
#include 
#include 

#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;
}
/************************* End of Sender ***********************/
/************************************************************/
/************************** Receiver *************************/
// 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:
//    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
//
#include 
#include 
#include 

#define DEFAULT_PORT            5150
#define DEFAULT_COUNT           25
#define DEFAULT_BUFFER_LENGTH   4096

int   iPort    = DEFAULT_PORT;          // Port to receive on
DWORD dwCount  = DEFAULT_COUNT,         // Number of messages to read
      dwLength = DEFAULT_BUFFER_LENGTH; // Length of receiving buffer
BOOL  bInterface = FALSE;               // Use an interface other than
                                        // default
char  szInterface[32];            // Interface to read datagrams from

//
// Function: usage:
//
// Description:
//    Print usage information and exit
//
void usage()
{
    printf("usage: sender [-p:int] [-i:IP][-n:x] [-b:x]\n\n");
    printf("       -p:int   Local port\n");
    printf("       -i:IP    Local IP address to listen on\n");
    printf("       -n:x     Number of times to send message\n");
    printf("       -b:x     Size of buffer to send\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':   // Local port
                    if (strlen(argv[i]) > 3)
                        iPort = atoi(&argv[i][3]);
                    break;
                case 'n':   // Number of times to receive 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 'i':	// Interface to receive datagrams on
					if (strlen(argv[i]) > 3)
					{
						bInterface = TRUE;
					strcpy(szInterface, &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 it to a local interface
//    and port, and then read datagrams.
//
int main(int argc, char **argv)
{
    WSADATA        wsd;
    SOCKET         s;
    char          *recvbuf = NULL;
    int            ret,
                   i;
    DWORD          dwSenderSize;
    SOCKADDR_IN    sender,
				   local;

    // Parse arguments and load Winsock
    //
    ValidateArgs(argc, argv);

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        printf("WSAStartup failed!\n");
        return 1;
    }
    // Create the socket and bind it to a local interface and port
    //
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == INVALID_SOCKET)
    {
        printf("socket() failed; %d\n", WSAGetLastError());
        return 1;
    }
    local.sin_family = AF_INET;
    local.sin_port = htons((short)iPort);
    if (bInterface)
        local.sin_addr.s_addr = inet_addr(szInterface);
    else
		local.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
    {
		printf("bind() failed: %d\n", WSAGetLastError());
		return 1;
    }
    // Allocate the receive buffer
    //
    recvbuf = GlobalAlloc(GMEM_FIXED, dwLength);
    if (!recvbuf)
    {
        printf("GlobalAlloc() failed: %d\n", GetLastError());
        return 1;
    }
    // Read the datagrams
    //
    for(i = 0; i < dwCount; i++)
    {
        dwSenderSize = sizeof(sender);
        ret = recvfrom(s, recvbuf, dwLength, 0,
                (SOCKADDR *)&sender, &dwSenderSize);
        if (ret == SOCKET_ERROR)
        {
            printf("recvfrom() failed; %d\n", WSAGetLastError());
            break;
        }
        else if (ret == 0)
            break;
		else
		{
			recvbuf[ret] = '\0';
			printf("[%s] sent me: '%s'\n",
				inet_ntoa(sender.sin_addr), recvbuf);
		}
    }
    closesocket(s);

    GlobalFree(recvbuf);
    WSACleanup();
    return 0;
}
/************************* End of Receiver **********************/

12 Comments

  1. Thank you so much. This is the best example of using udp I have found.

    I was using Borland C++ Builder 6 : TNMUDP. I could specify ports, hosts and the receive event, and call Activate, and then I could send a char * buffer and react to such in the receive event.

    Now I dont have that because I am trying to upgrade to a new compiler : CodeGear C++ Builder 2009.

    I have been studdying this socket stuff really hard the last days and nights, but it wasnt until I found this that I got the parameters and calls right. Most of the examples are about tcp, so its been hard to figure out what options to change and what calls to make.

    When I tried this it compiled almost imidiately. I tried to create a FillData event just after the memset, and I can set the data as I like. So I just need to turn the Sender and Receiver into a component, or maybe two components. Whatever is safest and simplest. Send is for me more important than receive.

    Could you advise how I simply can design the class that I need. I have a feeling that I should freshen up threads again, but I cant get a grip of turning this into a connection that will work for years.

    Anyway thanks for providing some really good examples.

  2. Ok it is just that, starting up a thread to handle the listening and providing the event for my application to read what the other says. And sending is done just like your example. I have now a window with a socket class that has your two methods Sender and Receiver. For receiving I press a button and in another instance of my test application I call send in another. I have incresed received count to 10 and can press send button 10 times in the other application where count is one, and I can send safely as long as my receiver dosnt stop.
    The thing that I more specifficly need help for is these questions:

    Do I use 1 or 2 sockets for creating this component?
    The way I see it one socket is always hanging in the recv call in the thread, so I have to use another socket instance to send from. Can I create 2 instances of socket with the same parameters for address and port. I am not interested in callback. Any short messages and messages from other than my client are irrelevant and disgarded anyway.

    Do I make two separate components one for read and one for write or is it smarter to make one component with 2 sockets or do I have to use the same socket because nothing else is possible.

    I can see how to make a component that creates a thread and starts causing events when something is received. I dont see a way to make that socket handle send when I need it.

    • Thanks for the comment. Source code is now available and you can download it from this post.

  3. Hello, Would it be possible to send me the source code for this UDP Sender and Receiver sample? It would help me tremendously for a class HW assignment. I need to find out C++ and Otcl code implementing UDP. Thanks in advance. jcofino@gmail.com

    • Thanks for the comment. Source code is now available and you can download it from this post.

    • Hi, Saqib,
      Somehow I cannot download the source code..and #include parts are missing..

      could you please assist?

      thanks

  4. Hello, i am in new in this area. in the code #include, what header am i suppose to include??

    or how can i try out this code? i am using codeblock.

  5. Hello,

    first of all, thank you for the source code! It runs just fine by including

    #include
    #include
    #include
    #include
    #include

    in the header. I am trying to compile the sender code using VisualStudio(2012) with a C++ project. Unfortunately I got the following error that stymies me to go ahead:

    line 170) C2440 cannot convert from Hglobal to char
    line 170) HGLOBAL cannot be assigned to an entity of type char

    it refers to line 126 where we declare

    char *sendbuf = NULL;

    I have to add that I am quite new to the C/C++ coding and even newer to UDP/IP communication so it could be I am missing something of the global picture :) could you help me out?

    Thanks!

    U

    PS

    in the C++ code I included also the following line in the header to make it run with VS

    #pragma comment(lib,”ws2_32.lib”)

Leave a Reply