Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing UDP Communication with sendto and recvfrom Functions

Tech May 9 4

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 family
  • SOCK_DGRAM: Designates a datagram socket for connectionless UDP communication
  • 0 (or IPPROTO_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 information
  • address_length: Typical set to sizeof(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 port
  • address_length: Set to sizeof(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

  1. Zero return: Indicates remote peer closed connection

    • Close socket descriptor
    • Remove from monitoring sets (FD_CLR for select, automatic for epoll)
  2. Positive value less than buffer size: Data completely read

    • Equal to buffer size may indicate more data pending
  3. Negative return (-1): Error conditions

    • EAGAIN/EWOULDBLOCK: No data available, retry later
    • EINTR: Operation interrupted, can retry
    • Other errors: Close socket connection

send/sendto Return Values

  1. Negative return (-1): Error conditions

    • EAGAIN/EWOULDBLOCK: Buffer full, wait for write readiness
    • EINTR: Interrupted, can retry
    • Other errors: Close socket
  2. 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;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.