C Programming

How to Implement the UDP Sockets in C

The implementation of UDP (User Datagram Protocol) sockets in the C language provide a good solution for network communication. UDP operates on top of the IP address and it is commonly used for applications where low latency and efficiency are essential. Let us discuss about how to implement the UDP sockets in the C language. We will explain both on the server-side and client-side. Using the socket functions, address configuration, and data sending or receiving methods, we can establish reliable and efficient communication channels between the server and client applications.

Definition of UDP

UDP (User Datagram Protocol) is a transport layer protocol that offers a straightforward and lightweight mechanism to transmit and receive the datagrams across a network. As a connection less and unreliable protocol, UDP prioritizes simplicity and efficiency over reliability and error recovery mechanisms provided by other protocols like TCP.

UDP is often used in situations where real-time and low-latency communication is important. The simplicity of UDP is one of its primary characteristics. UDP does not initially create a connection between the sender and recipient as TCP does. However, it sees each datagram as a separate entity which allows for the possibility of packets arriving out of sequence, being lost, or being duplicated. As a result, UDP cannot ensure the data delivery or sequencing.

As we know, UDP is lightweight and it is frequently used for various applications and protocols. For example, DNS (Domain Name System) relies on UDP to quickly resolve the domain names to IP addresses. DHCP (Dynamic Host Configuration Protocol) use UDP to assign the IP addresses and network configuration to devices. Additionally, multimedia streaming applications such as video, and audio streaming services such as Zoom and Google Meet use UDP to provide a real-time data with low latency.

Let us see the following diagram to understand the implementation of UDP:

UDP implementation diagram

Implement the UDP Sockets in C

Programming Example 1: Server-Side Program

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#define SERVER_PORT 7070

#define BUFFER_SIZE 1024

int main ()

{

    int serverSocket;
    struct sockaddr_in serverAddress, clientAddress;
    char buffer[BUFFER_SIZE];

    // Create socket
    serverSocket = socket(AF_INET, SOCK_DGRAM, 0);


    if (serverSocket < 0) {

       perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    // Bind socket to port
    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddress.sin_port = htons(SERVER_PORT);

    if (bind (serverSocket, (struct sockaddr *) & serverAddress, sizeof(serverAddress)) < 0) {
        perror ("Binding failed");
        exit (EXIT_FAILURE);
    }

    // Receive and process data
    while (1) {
        socklen_t clientAddressLength = sizeof(clientAddress);
        ssize_t dataLength = recvfrom(serverSocket, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&clientAddress, &clientAddressLength);


    if (dataLength < 0) {

            perror ("Error in receiving data");
            exit (EXIT_FAILURE);
        }

        // Process received data
        printf("Server received: %s\n", buffer);

        // reply back to client server
        sendto(serverSocket, "Server response", strlen("Server response"), 0, (struct sockaddr *)&clientAddress, clientAddressLength);
    }

    close (serverSocket);
    return 0;


}

Programming Example 2: Client-Side Program

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#define SERVER_PORT 7070

#define BUFFER_SIZE 1024

int main () {

    int clientSocket;
    struct sockaddr_in serverAddress;
    char buffer[BUFFER_SIZE];
    const char *message = "this is a message";

    // Create socket
    clientSocket = socket (AF_INET, SOCK_DGRAM, 0);


    if (clientSocket < 0) {

        perror ("Socket creation failed");
        exit (EXIT_FAILURE);
    }

    // Configure server address
    memset (&serverAddress, 0, sizeof (serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons (SERVER_PORT);

    if (inet_pton(AF_INET, "127.0.0.1", &(serverAddress.sin_addr)) <= 0) {

        perror ("Invalid address");
        exit (EXIT_FAILURE);
    }

    // Send message to the server


    if (sendto(clientSocket, message, strlen (message), 0, (struct sockaddr *) & serverAddress, sizeof (serverAddress)) < 0) {

        perror ("Error in sending data");
        exit (EXIT_FAILURE);
    }

    // Receive response from the server
    ssize_t responseLength = recvfrom(clientSocket, buffer, BUFFER_SIZE, 0, NULL, NULL);

    if (responseLength < 0) {

        perror ("Error in receiving response");
        exit (EXIT_FAILURE);
    }

    // Process the received response
    buffer [responseLength] = '\0';
    printf ("Client received: %s\n", buffer);

    close (clientSocket);
    return 0;


}

Output:

** server-side output**

$ gcc ser.c -o ser

$ ./ser

Server received: this is a message

** client-side output **

gcc cli.c -o cli

./cli

Client received: Server response

Explanation:

We first use the “socket()” function in the UDP server-side and client-side program to implement a UDP socket. After that, we set the address of the client for the client-side code. We define the server address for the server-side code. The socket is then enabled to receive the data using the “bind()” command to connect it to the server’s address. Here in the program, the client uses the “sendto()” function to send the data to the server. After that, only the server uses the “recvfrom()” function to receive the data from the client and keeps it in a buffer. The “recvfrom()” function uses the client to get the server’s response. At last, the program displays it in the terminal or command prompt.

Conclusion

The implementation of UDP sockets in the C language provides us with a very simple process to communicate between the server and client applications. UDP allows us for the exchange of datagrams over a network. UDP also makes it suitable for scenarios where low latency is preferred. Using the UDP socket functions, address configuration, and data sending operations, we can get better communication between the server and the client.

About the author

Bamdeb Ghosh

Bamdeb Ghosh is having hands-on experience in Wireless networking domain.He's an expert in Wireshark capture analysis on Wireless or Wired Networking along with knowledge of Android, Bluetooth, Linux commands and python. Follow his site: wifisharks.com