An Intro to Windows Socket (Winsock2) Programming 19

 

 

 

Running Both the UDP Receiver/Server and UDP Sender/Client

 

In this test we run both the server and client program on the same host.

 

1.   Firstly run the previous UDPReceiver program.

 

 

The UDP sender connectionless select Winsock2 and C program: the UDP select server/receiver program in action, waiting client to send datagrams

 

2.   Then run the UDPSender program. The following screenshot shows both outputs.

 

The UDP sender connectionless select Winsock2 and C program: the client and server program in action for the UDP select server with C code

 

Well, you have seen the issue here how the server/receiver can be in the 'listening' mode similar to the TCP counterpart. The recvfrom() part can be put in a loop to achieve this and/or for a better solution, you can use the select() function by setting the timeout and other simple features which provide more controls on the program behaviors. The code snippet is shown below.

 

int recvfromTimeOutUDP(SOCKET socket, long sec, long usec)

{

    // Setup timeval variable

    timeval timeout;

    timeout.tv_sec = sec;

    timeout.tv_usec = usec;

    // Setup fd_set structure

    fd_set fds;

    FD_ZERO(&fds);

    FD_SET(socket, &fds);

    // Return value:

    // -1: error occured

    // 0: timed out

    // > 0: data ready to be read

    return select(0, &fds, 0, 0, &timeout);

}

 

 

SelectTiming = recvfromTimeOutUDP(s, 20, 30);

switch (SelectTiming)

{

case 0:

    // Timed out, do whatever you want to handle this situation

    break;

case -1:

    // Error occured, maybe we should display an error message?

    break;

default:

    // Ok the data is ready, call recvfrom() to get it then

    recvfrom(ReceivingSocket, ReceiveBuf, BufLength, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);

}

 

A sample of the working program example that uses the select() function is given below. The project name is UDPServerVer2.

 

 

#include <winsock2.h>

#include <stdio.h>

 

// A sample of the select() return value

int recvfromTimeOutUDP(SOCKET socket, long sec, long usec)

{

    // Setup timeval variable

    struct timeval timeout;

            struct fd_set fds;

 

    timeout.tv_sec = sec;

    timeout.tv_usec = usec;

    // Setup fd_set structure

    FD_ZERO(&fds);

    FD_SET(socket, &fds);

    // Return value:

    // -1: error occured

    // 0: timed out

    // > 0: data ready to be read

    return select(0, &fds, 0, 0, &timeout);

}

 

int main(int argc, char **argv)

{

            WSADATA                            wsaData;

            SOCKET                                ReceivingSocket;

            SOCKADDR_IN                   ReceiverAddr;

            int                                            Port = 5150;

            char                             ReceiveBuf[1024];

            int                                            BufLength = 1024;

            SOCKADDR_IN                   SenderAddr;

            int                                            SenderAddrSize = sizeof(SenderAddr);

            int                                            ByteReceived = 5, SelectTiming, ErrorCode;

            char ch = 'Y';

           

   // Initialize Winsock version 2.2

   if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0)

   {

               printf(Server: WSAStartup failed with error %ld\n, WSAGetLastError());

               return -1;

   }

   else

                        printf(Server: The Winsock DLL status is %s.\n, wsaData.szSystemStatus);

           

            // Create a new socket to receive datagrams on.

            ReceivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

 

            if (ReceivingSocket == INVALID_SOCKET)

            {

                        printf(Server: Error at socket(): %ld\n, WSAGetLastError());

                        // Clean up

                        WSACleanup();

                        // Exit with error

                        return -1;

            }

            else

                        printf(Server: socket() is OK!\n);

 

            // Set up a SOCKADDR_IN structure that will tell bind that we

            // want to receive datagrams from all interfaces using port 5150.

 

            // The IPv4 family

            ReceiverAddr.sin_family = AF_INET;

            // Port no. 5150

            ReceiverAddr.sin_port = htons(Port);

            // From all interface (0.0.0.0)

            ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

           

   // Associate the address information with the socket using bind.

   // At this point you can receive datagrams on your bound socket.

   if (bind(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr)) == SOCKET_ERROR)

   {

               printf(Server: bind() failed! Error: %ld.\n, WSAGetLastError());

               // Close the socket

               closesocket(ReceivingSocket);

               // Do the clean up

               WSACleanup();

               // and exit with error

               return -1;

            }

            else

                        printf(Server: bind() is OK!\n);

 

   // Some info on the receiver side...

   getsockname(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, (int *)sizeof(ReceiverAddr));

 

   printf(Server: Receiving IP(s) used: %s\n, inet_ntoa(ReceiverAddr.sin_addr));

   printf(Server: Receiving port used: %d\n, htons(ReceiverAddr.sin_port));

  

   printf(Server: I\'m ready to receive a datagram...\n);

 

   SelectTiming = recvfromTimeOutUDP(ReceivingSocket, 10, 0);

 

   switch (SelectTiming)

               {

                           case 0:

                                       // Timed out, do whatever you want to handle this situation

                                       printf(Server: Timeout lor while waiting you bastard client!...\n);

                                       break;

                           case -1:

                                       // Error occured, maybe we should display an error message?

                                       // Need more tweaking here and the recvfromTimeOutUDP()...

                                       printf(Server: Some error encountered with code number: %ld\n, WSAGetLastError());

                                       break;

                           default:

                                       {

                                                   while (1)

                                                   {

                                                               // Call recvfrom() to get it then display the received data...

                                                               ByteReceived = recvfrom(ReceivingSocket, ReceiveBuf, BufLength, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);

                                                               if ( ByteReceived > 0 )

                                                               {

                                                                           printf(Server: Total Bytes received: %d\n, ByteReceived);

                                                                           printf(Server: The data is \%s\\n, ReceiveBuf);

                                                               }

                                                               else if ( ByteReceived <= 0 )

                                                                           printf(Server: Connection closed with error code: %ld\n, WSAGetLastError());

                                                               else

                                                                           printf(Server: recvfrom() failed with error code: %d\n, WSAGetLastError());

                                                              

                                                               // Some info on the sender side

                                                               getpeername(ReceivingSocket, (SOCKADDR *)&SenderAddr, &SenderAddrSize);

                                                               printf(Server: Sending IP used: %s\n, inet_ntoa(SenderAddr.sin_addr));

                                                               printf(Server: Sending port used: %d\n, htons(SenderAddr.sin_port));

                                                   }

                                       }

   }

 

   // When your application is finished receiving datagrams close the socket.

   printf(Server: Finished receiving. Closing the listening socket...\n);

   if (closesocket(ReceivingSocket) != 0)

               printf(Server: closesocket() failed! Error code: %ld\n, WSAGetLastError());

   else

               printf(Server: closesocket() is OK...\n);

           

   // When your application is finished call WSACleanup.

   printf(Server: Cleaning up...\n);

   if(WSACleanup() != 0)

               printf(Server: WSACleanup() failed! Error code: %ld\n, WSAGetLastError());

   else

               printf(Server: WSACleanup() is OK\n);

   // Back to the system

            return 0;

}

 

When we run the UDP receiver/server program, while there is no client connection in 10 seconds, the program terminates.

 

The UDP sender connectionless select Winsock2 and C program: the UDp receiver/server with select features sample console output

 

The following screenshot shows that when there are connections, the socket keeps opening and listening. We test the same client (UDPSender), by sending multiple UDP datagrams. You may want to test this program with the client 'connected' or sending the datagram from different hosts, in private or public network. The following screenshot shows the sender output samples.

 

The UDP sender connectionless select Winsock2 and C program: the UDP sender/client in actions, sending three datagrams through console output

 

The following screenshot shows the receiver sample output. Keep in mind that both receiver and sender programs were run on the same host.

 

 

The UDP sender connectionless select Winsock2 and C program: the UDP select server in action receiving datagrams from clients/sender through console output

 

 

 

< Winsock2 18 | Windows Socket 2 (Winssock2) | Win32 Programming | Winsock2 20 >