UDP Notes
UDP, or User Datagram Protocol, is a key protocol in the Internet Protocl (IP) suite, functioning at the transport layer. UDP is a connectionless protocol, meaning it does not establish a dedicated connection before data transmission (no handshake). It sends data in discret packets called datagrams, each independent of the others.
Unlike its counterpart TCP, UDP provides no guarantees of delivery, order, or error correction. This simplicity makes UDP lightweight and highly efficient for applications where speed and low latency are more critical than perfect accuracy or reliability. With its small header size of 8 bytes, UDP adds minimal overhead to data transmission, making it ideal for time-sensitive and high-performance tasks. However, developers using UDP must implement their own mechanisms for error handling and retransmission if reliability is required.
APIs
// send data from a socket to a specific destination
ssize_t sendto(
int sockfd, // [in] The socket file descriptor (created with `socket()`)
const void *buf, // [in] Pointer to the data buffer to be sent
size_t len, // [in] Length of the data in bytes
int flags, // [in] Flags for special options (usually 0 for default behavior)
const struct sockaddr *dest_addr, // [in] Pointer to the destination address (e.g., server's address)
socklen_t addrlen // [in] Size of the destination address structure
);
// receive data on a socket and also retrieve the address of the sender
ssize_t recvfrom(
int sockfd, // [in] The socket file descriptor (created with `socket()`)
void *buf, // [out] Pointer to the buffer to store the received data
size_t len, // [in] Maximum length of the buffer
int flags, // [in] Flags for special options (usually 0 for default behavior)
struct sockaddr *src_addr, // [out] Pointer to a structure where the sender's address will be stored
socklen_t *addrlen // [in/out] Pointer to the size of the sender's address structure
);
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define PORT 8001
#define BUFFER_SIZE 1024
int main() {
// create a udp socket (datagram socket)
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0) {
perror("create socket");
exit(EXIT_FAILURE);
}
// bind address
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int status = bind(socket_fd, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (status < 0) {
perror("bind socket");
close(socket_fd);
exit(EXIT_FAILURE);
}
printf("server is running on port %d...\n", PORT);
// receive data
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[BUFFER_SIZE];
ssize_t count = recvfrom(socket_fd, buffer, BUFFER_SIZE-1, 0, (struct sockaddr *)&client_addr, &client_len);
if (count < 0) {
perror("receive failed");
exit(EXIT_FAILURE);
}
buffer[count] = '\0'; // null-terminated the string
printf("received: '%s', %zu bytes\n", buffer, count);
// send a response
const char *response = "hello from udp server";
count = sendto(socket_fd, response, strlen(response), 0, (const struct sockaddr *)&client_addr, client_len);
if (count < 0) {
perror("failed to send");
}
printf("response sent %zu bytes\n", count);
// clean up, close socket
close(socket_fd);
return 0;
}
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8001
#define BUFFER_SIZE 1024
#define SERVER_IP "127.0.0.1"
int main() {
char buffer[BUFFER_SIZE];
// create a udp socket (datagram socket)
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0) {
perror("create socket");
exit(EXIT_FAILURE);
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// send data to the server
const char *message = "hi from udp client";
ssize_t count = sendto(socket_fd, message, strlen(message), 0, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (count < 0) {
perror("failed to send");
} else {
printf("[client] send '%s', %zu bytes\n", message, count);
}
socklen_t server_len = sizeof(server_addr);
// receive response
count = recvfrom(socket_fd, buffer, BUFFER_SIZE-1, 0, (struct sockaddr *)&server_addr, &server_len);
if (count < 0) {
perror("failed to receive");
} else {
buffer[count] = '\0';
printf("[client] received response '%s', %zu bytes\n", buffer, count);
}
// clean up, close socket
close(socket_fd);
return 0;
}