[Previous] [Contents] [Next]

Lesson 5:
A Winsock UDP receiver

 

Introduction

This is the easiest lesson yet. A UDP receiver binds a socket to an interface and then calls a function that waits for a UDP packet, that’s it.

 

Initialization and socket creation

You learned about the initialization process in Lesson 2 and the UDP socket creation in Lesson 4, so this won’t be too hard:

 

// author:               frenchwhale (http://frenchwhales_site.tripod.com)
//                       for the WinSock tutorial
//
// file name:            wsudprcv.c
//
// description:          A UDP packet receiver that waits for
//                       UDP packets on a specific port
// Copyright 2002 frenchwhale

 

#include <winsock.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

int main(int argc, int **argv)

{

   WSADATA wsda;        // Structure to store info

                             // returned from WSAStartup

 

   char szMessage[512];

   int iMessageLen;

   int ret;

 

   char szAddress[64];

   int iPort;

 

   SOCKET s;                      // Our TCP socket handle

   SOCKADDR_IN addr,              // The local interface address

               remote_addr;       // The sender's address

   int iRemoteAddrLen;            // Contains the length of remte_addr, passed to recvfrom

 

   // Check arguments

   if(argc != 2 ||

      (argc==2 && strcmp((char *) &argv[1][0], "/?")==0))

   {

      printf("wsudprcv port\n");

      printf("   port:   the port the server should listen to\n");

      exit(1);

   }

 

   // Get the remote port

   iPort = atoi((char *) &argv[1][0]);

 

   if(iPort<0 || iPort>65563)

   {

      printf("Invalid port number! (%s)\n", argv[2]);

      exit(1);

   }

 

   iMessageLen = 512;             // Set to the length of szMessage buffer

 

   // Load version 1.1 of Winsock

 

   WSAStartup(MAKEWORD(1,1), &wsda);

 

   // Create an UDP socket

   printf("Creating socket...");

   s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

 

   // Error?

   if(s == SOCKET_ERROR)

   {

      printf("Error\nCall to socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); failed with:\n%d\n", WSAGetLastError());

      exit(1);

   }

 

   printf("OK\n");

 

Binding, receiving and cleanup

In order to receive any packets on a socket, it has to be bound to an interface. All this is discussed thoroughly in Lesson 3, but I will include the function declaration here, just for review:

 

int bind(SOCKET s, struct sockaddr FAR *addr, int addrlen);

 

Where s is the socket handle, addr is a pointer to a sockaddr structure containing the local interface address and port number and addrlen is the length of this structure. Remember that you usually bind a socket to INADDR_ANY to listen on all interfaces.

The other function we will encounter is recvfrom, declared as:

int recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);

Where s is the socket handle, buf is a pointer to a buffer where the UDP data will be stored, len is the length of the buffer, flags specifies some flags that should be used (we won’t use any, just set it to 0), from is a pointer to a structure where the address of the sender will be stored and lastly, fromlen is a pointer to an int containing the length of the sockaddr structure. So when you call this function, you supply a data buffer and a sockaddr structure, upon return, the data buffer will be filled with the data that was in the packet and the sockaddr structure will contain information about the sender.

This part of the code binds the socket, waits for a packet, prints the content of it and then cleans up:

 

   // Fill in the interface information

   printf("Binding socket...");

   addr.sin_family = AF_INET;

   addr.sin_port = htons(iPort);

   addr.sin_addr.s_addr = INADDR_ANY;

 

   if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR)

   {

      printf("Error\nCall to bind(s, (struct sockaddr *) &addr, sizeof(addr)); failed with:\n%d\n", WSAGetLastError());

      exit(1);

   }

   printf("OK\n");

 

   // Ready to receive data

 

   printf("Waiting for packets (Press Ctrl-C to exit)...");

 

   iRemoteAddrLen = sizeof(remote_addr);

   ret = recvfrom(s, szMessage, iMessageLen, 0, (struct sockaddr *) &remote_addr, &iRemoteAddrLen);

 

   if(ret == SOCKET_ERROR)

   {

      printf("Error\nCall to recvfrom(s, szMessage, iMessageLen, 0, (struct sockaddr *) &remote_addr, &iRemoteAddrLen); failed with:\n%d\n", WSAGetLastError());

      exit(1);

   }

   printf("Packet received\n");

 

   iMessageLen = ret;        // Length of the data received

 

   szMessage[iMessageLen] = '\0';     // Convert to cstring

 

   printf("\"%s\" received from %s\n", szMessage, inet_ntoa(remote_addr.sin_addr));

 

   closesocket(s);

 

   WSACleanup();

 

   return 0;

}

 

Source code for Lesson 5:

n       WSUDPRCV.C – Listens for a UDP packet to arrive at a specified port.

 

[Previous] [Contents] [Next]