Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Linux Socket Programming for Client-Server Communication

Tech May 18 2

TCP Server Implementation

This example demonstrates a TCP echo server using epoll for efficient I/O multiplexing:

#include <sys/epoll.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_EVENTS 20
#define BUFFER_CAPACITY 4096

int create_listening_socket(int port_number, const char* interface_addr) {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in addr_config;
    memset(&addr_config, 0, sizeof(addr_config));
    addr_config.sin_family = AF_INET;
    addr_config.sin_port = htons(port_number);
    
    if (interface_addr) {
        inet_pton(AF_INET, interface_addr, &addr_config.sin_addr);
    } else {
        addr_config.sin_addr.s_addr = INADDR_ANY;
    }

    if (bind(fd, (struct sockaddr*)&addr_config, sizeof(addr_config)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }

    if (listen(fd, 20) < 0) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }
    return fd;
}

int main(int argc, char** argv) {
    int port = 8080;
    const char* bind_addr = NULL;

    // Command-line argument parsing omitted for brevity
    
    int listen_sock = create_listening_socket(port, bind_addr);
    int epoll_fd = epoll_create1(0);
    
    struct epoll_event initial_event;
    initial_event.events = EPOLLIN;
    initial_event.data.fd = listen_sock;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &initial_event);

    struct epoll_event events[MAX_EVENTS];
    char data_buffer[BUFFER_CAPACITY];

    while (1) {
        int ready_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        for (int i = 0; i < ready_count; i++) {
            if (events[i].data.fd == listen_sock) {
                struct sockaddr_in client_addr;
                socklen_t addr_size = sizeof(client_addr);
                int client_fd = accept(listen_sock, (struct sockaddr*)&client_addr, &addr_size);
                
                struct epoll_event new_client;
                new_client.events = EPOLLIN;
                new_client.data.fd = client_fd;
                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &new_client);
            } else {
                ssize_t bytes_read = recv(events[i].data.fd, data_buffer, BUFFER_CAPACITY, 0);
                if (bytes_read <= 0) {
                    close(events[i].data.fd);
                    continue;
                }
                send(events[i].data.fd, data_buffer, bytes_read, 0);
            }
        }
    }
    close(listen_sock);
    return 0;
}

TCP Client Implementation

This TCP client establishes a connection and exchanges messages with a server:

#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv) {
    const char* server_ip = "127.0.0.1";
    int port = 8080;
    
    int connection_fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in server_config;
    memset(&server_config, 0, sizeof(server_config));
    server_config.sin_family = AF_INET;
    server_config.sin_port = htons(port);
    inet_pton(AF_INET, server_ip, &server_config.sin_addr);

    connect(connection_fd, (struct sockaddr*)&server_config, sizeof(server_config));
    
    const char* message = "Test message";
    send(connection_fd, message, strlen(message), 0);
    
    char response[1024];
    ssize_t bytes_received = recv(connection_fd, response, sizeof(response), 0);
    response[bytes_received] = '\0';
    printf("Server response: %s\n", response);
    
    close(connection_fd);
    return 0;
}

UDP Server Implementation

UDP echo server implementation using datagram sockets:

#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main() {
    int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in server_config;
    memset(&server_config, 0, sizeof(server_config));
    server_config.sin_family = AF_INET;
    server_config.sin_port = htons(8080);
    server_config.sin_addr.s_addr = INADDR_ANY;
    
    bind(socket_fd, (struct sockaddr*)&server_config, sizeof(server_config));
    
    while (1) {
        char datagram[1024];
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        
        ssize_t recv_size = recvfrom(socket_fd, datagram, sizeof(datagram), 0,
                                    (struct sockaddr*)&client_addr, &client_len);
        sendto(socket_fd, datagram, recv_size, 0,
              (struct sockaddr*)&client_addr, client_len);
    }
    close(socket_fd);
    return 0;
}

UDP Client Implementation

UDP client that sends messages and receives responses:

#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main() {
    int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in server_config;
    memset(&server_config, 0, sizeof(server_config));
    server_config.sin_family = AF_INET;
    server_config.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &server_config.sin_addr);
    
    const char* message = "UDP test";
    sendto(socket_fd, message, strlen(message), 0,
          (struct sockaddr*)&server_config, sizeof(server_config));
    
    char response[1024];
    recvfrom(socket_fd, response, sizeof(response), 0, NULL, NULL);
    printf("Server reply: %s\n", response);
    
    close(socket_fd);
    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.