Unit5 How To Implement UDP Sockets in C

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 23

How to implement UDP sockets in C

UDP is a connection-less protocol that, unlike TCP, does not require


any handshaking prior to sending or receiving data, which simplifies its
implementation.

Server-side
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(void){
    int socket_desc;
    struct sockaddr_in server_addr, client_addr;
    char server_message[2000], client_message[2000];
    int client_struct_length = sizeof(client_addr);
    
    // Clean buffers:
    memset(server_message, '\0', sizeof(server_message));
    memset(client_message, '\0', sizeof(client_message));
    
    // Create UDP socket:
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    if(socket_desc < 0){
        printf("Error while creating socket\n");
        return -1;
    }
    printf("Socket created successfully\n");
    
    // Set port and IP:
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // Bind to the set port and IP:
    if(bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
        printf("Couldn't bind to the port\n");
        return -1;
    }
    printf("Done with binding\n");
    
    printf("Listening for incoming messages...\n\n");
    
    // Receive client's message:
    if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,
         (struct sockaddr*)&client_addr, &client_struct_length) < 0){
        printf("Couldn't receive\n");
        return -1;
    }
    printf("Received message from IP: %s and port: %i\n",
           inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    
    printf("Msg from client: %s\n", client_message);
    
    // Respond to client:
    strcpy(server_message, client_message);
    
    if (sendto(socket_desc, server_message, strlen(server_message), 0,
         (struct sockaddr*)&client_addr, client_struct_length) < 0){
        printf("Can't send\n");
        return -1;
    }

    
    // Close the socket:
    close(socket_desc);
    
    return 0;
}

Explanation
Include the header file <sys/socket.h> and arpa/inet.h:

#include <sys/socket.h>
#include <arpa/inet.h>

Create a socket that returns a socket descriptor. This is used to refer to the socket later
on in the code:

int socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

The server-side code keeps the address information of both the server and the client in
the variable server_addr (a struct of type sockaddr_in). Initialize the server address by
the port and IP:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(2000);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Bind socket descriptor to the server address:

bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr);

Unlike TCP, the server-side does not wait for a client to connect and, therefore, does not
receive the client’s address prior to sending and receiving data. Instead, the server
receives information about the client when it receives data using the recvfrom() method:

int client_struct_length = sizeof(client_addr);

recvfrom(socket_desc, client_message, sizeof(client_message), 0,
           (struct sockaddr*)&client_addr, &client_struct_length);

The client’s information, stored in the variable client_addr of type sockaddr_in, is then


used to send data to the same client:

sendto(socket_desc, server_message, strlen(server_message), 0,
         (struct sockaddr*)&client_addr, client_struct_length);

Close the socket to end the communication:

close(socket_desc);
Client-side
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(void){
    int socket_desc;
    struct sockaddr_in server_addr;
    char server_message[2000], client_message[2000];
    int server_struct_length = sizeof(server_addr);
    
    // Clean buffers:
    memset(server_message, '\0', sizeof(server_message));
    memset(client_message, '\0', sizeof(client_message));
    
    // Create socket:
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    if(socket_desc < 0){
        printf("Error while creating socket\n");
        return -1;
    }
    printf("Socket created successfully\n");
    
    // Set port and IP:
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // Get input from the user:
    printf("Enter message: ");
    gets(client_message);
    
    // Send the message to server:
    if(sendto(socket_desc, client_message, strlen(client_message), 0,
         (struct sockaddr*)&server_addr, server_struct_length) < 0){
        printf("Unable to send message\n");
        return -1;
    }
    
    // Receive the server's response:
    if(recvfrom(socket_desc, server_message, sizeof(server_message), 0,
         (struct sockaddr*)&server_addr, &server_struct_length) < 0){
        printf("Error while receiving server's msg\n");
        return -1;
    }
    
    printf("Server's response: %s\n", server_message);
    
    // Close the socket:
    close(socket_desc);
    
    return 0;
}

Explanation

Include header files, create a socket, and initialize the server’s address information in a
variable of type sockaddr_in (similarly to how it was done at the server-side):

#include <sys/socket.h>
#include <arpa/inet.h>

int socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(2000);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

Unlike TCP, when the client sends and receives data using sendto() and recvfrom(), the
server’s information has to be given every time:

sendto(socket_desc, client_message, strlen(client_message), 0,
         (struct sockaddr*)&server_addr, server_struct_length);

recvfrom(socket_desc, server_message, sizeof(server_message), 0,
         (struct sockaddr*)&server_addr, &server_struct_length);

A deadlock will occur if both the client and the server are waiting for each other’s message
at recvfrom().
Client-server app

The following client-server application enables a client to connect to a server and


send only one message. The server replies with the same message converted to
uppercase letters and the communication terminates.

Instructions

1. Click the Run button in the widget below and execute the command for the Server. If the
socket is created successfully, the message Listening for incoming messages… will be
displayed.
2. Press the + button to open another terminal tab and execute the Client’s command.
3. Enter a message in the Client tab that is sent to the Server.
4. The Server’s response will be shown in the Client’s tab.

Server Client

usercode/server usercode/client
UDP_SERVER

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(void){
    int socket_desc;
    struct sockaddr_in server_addr, client_addr;
    char server_message[100], client_message[100];
    int client_struct_length = sizeof(client_addr);
    
    // Clean buffers:
    memset(server_message, '\0', sizeof(server_message));
    memset(client_message, '\0', sizeof(client_message));
    
    // Create UDP socket:
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    if(socket_desc < 0){
        printf("Error while creating socket\n");
        return -1;
    }
    printf("Socket created successfully\n");
    
    // Set port and IP:
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // Bind to the set port and IP:
    if(bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
        printf("Couldn't bind to the port\n");
        return -1;
    }
    printf("Done with binding\n");
    
    printf("Listening for incoming messages...\n\n");
    
    // Receive client's message:
    if (recvfrom(socket_desc, client_message, sizeof(client_message), 0,
         (struct sockaddr*)&client_addr, &client_struct_length) < 0){
        printf("Couldn't receive\n");
        return -1;
    }
    printf("Received message from IP: %s and port: %i\n",
           inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    
    printf("Msg from client: %s\n", client_message);
    
    // Change to uppercase:
    for(int i = 0; client_message[i]; ++i)
        client_message[i] = toupper(client_message[i]);
    
    // Respond to client:
    strcpy(server_message, client_message);
    
    if (sendto(socket_desc, server_message, strlen(server_message), 0,
         (struct sockaddr*)&client_addr, client_struct_length) < 0){
        printf("Can't send\n");
        return -1;
    }
    
    // Close the socket:
    close(socket_desc);

}
UDP_CLIENT.C

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(void){
    int socket_desc;
    struct sockaddr_in server_addr;
    char server_message[100], client_message[100];
    int server_struct_length = sizeof(server_addr);
    
    // Clean buffers:
    memset(server_message, '\0', sizeof(server_message));
    memset(client_message, '\0', sizeof(client_message));
    
    // Create socket:
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
    if(socket_desc < 0){
        printf("Error while creating socket\n");
        return -1;
    }
    printf("Socket created successfully\n");
    
    // Set port and IP:
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // Get input from the user:
    printf("Enter message: ");
    gets(client_message);
    
    // Send the message to server:
    if(sendto(socket_desc, client_message, strlen(client_message), 0,
         (struct sockaddr*)&server_addr, server_struct_length) < 0){
        printf("Unable to send message\n");
        return -1;
    }
    
    // Receive the server's response:
    if(recvfrom(socket_desc, server_message, sizeof(server_message), 0,
         (struct sockaddr*)&server_addr, &server_struct_length) < 0){
        printf("Error while receiving server's msg\n");
        return -1;
    }
    
    printf("Server's response: %s\n", server_message);
    
    // Close the socket:
    close(socket_desc);
    
    return 0;
}
UDP Client Server using connect | C
implementation
In UDP, the client does not form a connection with the server like in TCP and instead, It just
sends a datagram. Similarly, the server need not to accept a connection and just waits for
datagrams to arrive. We can call a function called connect() in UDP but it does not result
anything like it does in TCP. There is no 3 way handshake. It just checks for any immediate
errors and store the peer’s IP address and port number. connect() is storing peers address so
no need to pass server address and server address length arguments in sendto().

Necessary Functions :
int connect(int sockfd, const struct sockaddr *servaddr,
socklen_t addrlen);
returns : 0 if OK -1 on error
arguments :
sockfd : File descriptor of socket to be connected.
struct sockaddr *servaddr : server address structure.
addrlen : length of server address structure.
UDP Server code :
// server program for udp connection

#include <stdio.h>

#include <strings.h>

#include <sys/types.h>

#include <arpa/inet.h>

#include <sys/socket.h>

#include<netinet/in.h>

#define PORT 5000

#define MAXLINE 1000

// Driver code

int main()

char buffer[100];

char *message = "Hello Client";

int listenfd, len;

struct sockaddr_in servaddr, cliaddr;

bzero(&servaddr, sizeof(servaddr));

// Create a UDP Socket

listenfd = socket(AF_INET, SOCK_DGRAM, 0);

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(PORT);

servaddr.sin_family = AF_INET;

// bind server address to socket descriptor

bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));


//receive the datagram

len = sizeof(cliaddr);

int n = recvfrom(listenfd, buffer, sizeof(buffer),

0, (struct sockaddr*)&cliaddr,&len); //receive message from server

buffer[n] = '\0';

puts(buffer);

// send the response

sendto(listenfd, message, MAXLINE, 0,

(struct sockaddr*)&cliaddr, sizeof(cliaddr));

}
UDP Client code :
// udp client driver program

#include <stdio.h>

#include <strings.h>

#include <sys/types.h>

#include <arpa/inet.h>

#include <sys/socket.h>

#include<netinet/in.h>

#include<unistd.h>

#include<stdlib.h>

#define PORT 5000

#define MAXLINE 1000

// Driver code

int main()

char buffer[100];

char *message = "Hello Server";

int sockfd, n;

struct sockaddr_in servaddr;

// clear servaddr

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

servaddr.sin_port = htons(PORT);

servaddr.sin_family = AF_INET;

// create datagram socket


sockfd = socket(AF_INET, SOCK_DGRAM, 0);

// connect to server

if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)

printf("\n Error : Connect Failed \n");

exit(0);

// request to send datagram

// no need to specify server address in sendto

// connect stores the peers IP and port

sendto(sockfd, message, MAXLINE, 0, (struct sockaddr*)NULL, sizeof(servaddr));

// waiting for response

recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)NULL, NULL);

puts(buffer);

// close the descriptor

close(sockfd);

}
In UDP, the client does not form a connection with the server like in TCP and instead just
sends a datagram. Similarly, the server need not accept a connection and just waits for
datagrams to arrive. Datagrams upon arrival contain the address of sender which the server
uses to send data to the correct client.
The entire process can be broken down into following steps :
UDP Server :
1. Create UDP socket.
2. Bind the socket to server address.
3. Wait until datagram packet arrives from client.
4. Process the datagram packet and send a reply to client.
5. Go back to Step 3.
UDP Client :
1. Create UDP socket.
2. Send message to server.
3. Wait until response from server is recieved.
4. Process reply and go back to step 2, if necessary.
5. Close socket descriptor and exit.
Necessary Functions :
int socket(int domain, int type, int protocol)
Creates an unbound socket in the specified domain.
Returns socket file descriptor.
Arguments :
domain – Specifies the communication
domain ( AF_INET for IPv4/ AF_INET6 for IPv6 )
type – Type of socket to be created
( SOCK_STREAM for TCP / SOCK_DGRAM for UDP )
protocol – Protocol to be used by socket.
0 means use default protocol for the address family.
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
Assigns address to the unbound socket.
Arguments :
sockfd – File descriptor of socket to be binded
addr – Structure in which address to be binded to is specified
addrlen – Size of addr structure
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
Send a message on the socket
Arguments :
sockfd – File descriptor of socket
buf – Application buffer containing the data to be sent
len – Size of buf application buffer
flags – Bitwise OR of flags to modify socket behaviour
dest_addr – Structure containing address of destination
addrlen – Size of dest_addr structure
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
Receive a message from the socket.
Arguments :
sockfd – File descriptor of socket
buf – Application buffer in which to receive data
len – Size of buf application buffer
flags – Bitwise OR of flags to modify socket behaviour
src_addr – Structure containing source address is returned
addrlen – Variable in which size of src_addr structure is returned
int close(int fd)
Close a file descriptor
Arguments :
fd – File descriptor
In the below code, exchange of one hello message between server and client is shown to
demonstrate the model.
UDP_SERVER.C

// Server side implementation of UDP client-server model

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#define PORT 8080

#define MAXLINE 1024

// Driver code

int main() {

int sockfd;

char buffer[MAXLINE];

char *hello = "Hello from server";

struct sockaddr_in servaddr, cliaddr;

// Creating socket file descriptor

if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {

perror("socket creation failed");

exit(EXIT_FAILURE);

memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));

// Filling server information

servaddr.sin_family = AF_INET; // IPv4

servaddr.sin_addr.s_addr = INADDR_ANY;

servaddr.sin_port = htons(PORT);

// Bind the socket with the server address

if ( bind(sockfd, (const struct sockaddr *)&servaddr,

sizeof(servaddr)) < 0 )

perror("bind failed");

exit(EXIT_FAILURE);

int len, n;

len = sizeof(cliaddr); //len is value/resuslt

n = recvfrom(sockfd, (char *)buffer, MAXLINE,

MSG_WAITALL, ( struct sockaddr *) &cliaddr,

&len);

buffer[n] = '\0';

printf("Client : %s\n", buffer);

sendto(sockfd, (const char *)hello, strlen(hello),

MSG_CONFIRM, (const struct sockaddr *) &cliaddr,

len);

printf("Hello message sent.\n");


return 0;

UDP_CLIENT.C

// Client side implementation of UDP client-server model

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>

#define PORT 8080

#define MAXLINE 1024

// Driver code

int main() {

int sockfd;

char buffer[MAXLINE];

char *hello = "Hello from client";

struct sockaddr_in servaddr;

// Creating socket file descriptor

if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {

perror("socket creation failed");

exit(EXIT_FAILURE);

}
memset(&servaddr, 0, sizeof(servaddr));

// Filling server information

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(PORT);

servaddr.sin_addr.s_addr = INADDR_ANY;

int n, len;

sendto(sockfd, (const char *)hello, strlen(hello),

MSG_CONFIRM, (const struct sockaddr *) &servaddr,

sizeof(servaddr));

printf("Hello message sent.\n");

n = recvfrom(sockfd, (char *)buffer, MAXLINE,

MSG_WAITALL, (struct sockaddr *) &servaddr,

&len);

buffer[n] = '\0';

printf("Server : %s\n", buffer);

close(sockfd);

return 0;

Output :
$ ./server
Client : Hello from client
Hello message sent.
$ ./client
Hello message sent.
Server : Hello from server

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy