Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Understanding Synchronous and Asynchronous I/O with Five Network I/O Models

Tech May 8 3

Synchronous vs Asynchronous I/O

In synchronous I/O operations, the requesting process waits until the operation completes. This approach requires the initiator to block while data moves from kernel space to user space. The process either polls continuously or remains idle waiting for I/O readiness.

Conversely, asynchronous I/O allows processes to continue execution immediately after initiating an operation. Completion notifications arrive later via callbacks or signals. Data transfer occurs through kernel threads, eliminating blocking during the copy phase.

Five Network I/O Models

Each I/O read involves two phases:

  1. Waiting for data to become available in kernel buffers
  2. Copying data from kernel space to application memory

Linux provides five distinct I/O handling mechanisms:

Blocking I/O

The default socket behavior where system calls like recvfrom block until data arrives and is copied to user space. Applications remain suspended throughout both I/O phases.

Non-blocking I/O

Socket operations return immediately even when no data is ready. Applications repeatedly check for availability using polling loops. While the initial wait phase avoids blocking, copying data still requires suspension.

Configuration methods:

// During socket creation
int sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);

// Modifying existing socket
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);

I/O Multiplexing

Single-threaded applications monitor multiple file descriptors simultaneously. When any descriptor becomes active, the monitoring function returns control. Three primary implementations exist.

Select Model

Monitors three descriptor sets for readability, writability, and exceptions within specified timeouts:

#include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

// Helper macros
FD_ZERO(fd_set *fdset);     // Clear all bits
FD_SET(int fd, fd_set *fdset);   // Set specific bit
FD_CLR(int fd, fd_set *fdset);   // Clear specific bit
FD_ISSET(int fd, fd_set *fdset); // Test bit status

Server implementation example:

#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int server_socket, client_socket;
    struct sockaddr_in server_addr;
    fd_set active_fds, working_fds;
    
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    // Setup and bind server address...
    listen(server_socket, 5);
    
    FD_ZERO(&active_fds);
    FD_SET(server_socket, &active_fds);
    
    while(1) {
        working_fds = active_fds;
        select(FD_SETSIZE, &working_fds, NULL, NULL, NULL);
        
        for(int fd = 0; fd < FD_SETSIZE; fd++) {
            if(FD_ISSET(fd, &working_fds)) {
                if(fd == server_socket) {
                    // Handle new connection
                    client_socket = accept(server_socket, NULL, NULL);
                    FD_SET(client_socket, &active_fds);
                } else {
                    // Process client data
                    char buffer;
                    if(read(fd, &buffer, 1) <= 0) {
                        close(fd);
                        FD_CLR(fd, &active_fds);
                    } else {
                        buffer++;
                        write(fd, &buffer, 1);
                    }
                }
            }
        }
    }
}

Poll Model

Similar functionality to select but without hard limits on monitored descriptors:

#include <poll.h>

int poll(struct pollfd *fds, nfds_t count, int timeout_ms);

struct pollfd {
    int fd;         // File descriptor
    short events;   // Requested events
    short revents;  // Returned events
};

// Event types
POLLIN     // Data available for reading
POLLOUT    // Ready for writing
POLLERR    // Error condition

Poll-based server:

#include <poll.h>
#define MAX_CONNECTIONS 1024

int main() {
    struct pollfd connections[MAX_CONNECTIONS];
    int server_fd = setup_server();
    int active_count = 1;
    
    connections[0].fd = server_fd;
    connections[0].events = POLLIN;
    
    while(1) {
        poll(connections, active_count, 1000);
        
        for(int i = 0; i < active_count; i++) {
            if(connections[i].revents & POLLIN) {
                if(connections[i].fd == server_fd) {
                    // Accept new client
                    int client = accept(server_fd, NULL, NULL);
                    connections[active_count].fd = client;
                    connections[active_count].events = POLLIN;
                    active_count++;
                } else {
                    // Handle client request
                    char data;
                    if(read(connections[i].fd, &data, 1) <= 0) {
                        close(connections[i].fd);
                        // Remove from array
                    } else {
                        data++;
                        write(connections[i].fd, &data, 1);
                    }
                }
            }
        }
    }
}

Epoll Model

Advanced event notification interface providing better scalability than select/poll through edge-triggered and level-triggered modes.

Tags: io-models

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.