UDP is a connection-less protocol that, unlike TCP, does not require any handshaking prior to sending or receiving data, which simplifies its implementation.
#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;}
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);
#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;}
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()
.
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.
+
button to open another terminal tab and execute the Client’s command.Server | Client |
---|---|
usercode/server |
usercode/client |
#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); }