Implementing UDP Communication with sendto and recvfrom Functions
UDP Socket Creation
The socket(AF_INET, SOCK_DGRAM, 0) system call creates a UDP socket with the following parameters:
AF_INET: Specifies IPv4 address familySOCK_DGRAM: Designates a datagram socket for connectionless UDP communication0(orIPPROTO_UDP): Indicates the default UDP protocol
sendto() Function
int sendto(int socket_descriptor, const void *message_buffer, int buffer_length, unsigned int flags, const struct sockaddr *destination_address, int address_length);
This function transmits data to a specified destination. The additional parameters compared to send() are:
destination_address: Contains target IP and port informationaddress_length: Typical set tosizeof(struct sockaddr)
Returns the number of bytes sent or -1 on error.
recvfrom() Function
int recvfrom(int socket_descriptor, void *data_buffer, int buffer_size, unsigned int flags, struct sockaddr *source_address, int *address_length);
Receives data and stores the sender's address information:
source_address: Stores the source IP address and portaddress_length: Set tosizeof(struct sockaddr)before call, contains actual address size after return
Returns number of bytes received or -1 on error.
Return Value Handling
recv/recvfrom Return Values
-
Zero return: Indicates remote peer closed connection
- Close socket descriptor
- Remove from monitoring sets (FD_CLR for select, automatic for epoll)
-
Positive value less than buffer size: Data completely read
- Equal to buffer size may indicate more data pending
-
Negative return (-1): Error conditions
EAGAIN/EWOULDBLOCK: No data available, retry laterEINTR: Operation interrupted, can retry- Other errors: Close socket connection
send/sendto Return Values
-
Negative return (-1): Error conditions
EAGAIN/EWOULDBLOCK: Buffer full, wait for write readinessEINTR: Interrupted, can retry- Other errors: Close socket
-
Positive return: Bytes successfully sent
- Compare with intended send length
- Continue sending if partial transmission occurred
UDP Server Implementation
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SERVER_PORT 5678
#define BUFFER_CAPACITY 1024
#define MAX_FILENAME 512
int main() {
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(SERVER_PORT);
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
if (bind(udp_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Binding failed");
close(udp_socket);
exit(EXIT_FAILURE);
}
while (1) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
char request_buffer[BUFFER_CAPACITY];
memset(request_buffer, 0, BUFFER_CAPACITY);
int received_bytes = recvfrom(udp_socket, request_buffer, BUFFER_CAPACITY, 0,
(struct sockaddr*)&client_addr, &addr_len);
if (received_bytes > 0) {
char filename[MAX_FILENAME + 1];
memset(filename, 0, sizeof(filename));
strncpy(filename, request_buffer,
received_bytes > MAX_FILENAME ? MAX_FILENAME : received_bytes);
FILE *file_ptr = fopen(filename, "rb");
if (file_ptr) {
char transfer_buffer[BUFFER_CAPACITY];
size_t bytes_read;
while ((bytes_read = fread(transfer_buffer, 1, BUFFER_CAPACITY, file_ptr)) > 0) {
if (sendto(udp_socket, transfer_buffer, bytes_read, 0,
(struct sockaddr*)&client_addr, addr_len) < 0) {
perror("File transmission error");
break;
}
memset(transfer_buffer, 0, BUFFER_CAPACITY);
}
fclose(file_ptr);
}
}
}
close(udp_socket);
return 0;
}
UDP Client Implementation
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#define SERVER_PORT 5678
#define BUFFER_CAPACITY 1024
#define MAX_FILENAME 512
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <server_ip>\n", argv[0]);
exit(EXIT_FAILURE);
}
int client_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (client_sock < 0) {
perror("Client socket creation failed");
exit(EXIT_FAILURE);
}
struct timeval timeout = {1, 0}; // 1 second timeout
setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) <= 0) {
perror("Invalid server address");
close(client_sock);
exit(EXIT_FAILURE);
}
char filename[MAX_FILENAME];
printf("Enter filename to request: ");
scanf("%s", filename);
char buffer[BUFFER_CAPACITY];
memset(buffer, 0, BUFFER_CAPACITY);
strncpy(buffer, filename, BUFFER_CAPACITY - 1);
sendto(client_sock, buffer, strlen(buffer), 0,
(struct sockaddr*)&server_addr, sizeof(server_addr));
FILE *output_file = fopen(filename, "wb");
if (!output_file) {
perror("Output file creation failed");
close(client_sock);
exit(EXIT_FAILURE);
}
socklen_t addr_len = sizeof(server_addr);
int total_bytes = 0;
while (1) {
memset(buffer, 0, BUFFER_CAPACITY);
int bytes_received = recvfrom(client_sock, buffer, BUFFER_CAPACITY, 0,
(struct sockaddr*)&server_addr, &addr_len);
if (bytes_received <= 0) break;
fwrite(buffer, 1, bytes_received, output_file);
total_bytes += bytes_received;
}
printf("Received %d bytes for file %s\n", total_bytes, filename);
fclose(output_file);
close(client_sock);
return 0;
}