Files
cws/notes/advanced-techniques.md
2024-11-26 17:16:04 +01:00

2.9 KiB

Advanced Techniques

Blocking

All the Unix networking functions are blocking. What does it mean? It means that if you write accept() or recv() it will wait until some data appears. So how we can avoid this? Making the socket non blocking so we can poll the socket for info:

fcntl(sockfd, F_SETFL, O_NONBLOCK);

F_SETFL: set the file descriptor flags
O_NONBLOCK: make the fd non blocking

poll() - Synchronous I/O Multiplexing

The plan is to have a struct pollfd with the info about which sockets fd we want to monitor. The Operating System will block on the poll() call until one event occurs (e.g. "socket ready to write/read").

#include <poll.h>

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

fds is our array of info (which sockets to monitor)
nfds the elements in the array timeout in milliseconds (-1 to wait forever)

struct pollfd {
    int fd;         // the socket descriptor
    short events;   // bitmap of events we're interested in
    short revents;  // when poll() returns, bitmap of events that occurred
};

events is a bitmap of the following values:

  • POLLIN (alert when I can read data)
  • POLLOUT (alert when I can send data)

I won't continue this section, read below

epoll() - I/O Event Notification (Async)

It is similar to poll() but more efficient when dealing with lots of fds. The array is in the kernel space, no further copies. Nice explaination here.

#include <sys/epoll.h>

int epoll_create1(int flags);

Just pass 0 for the flags, it is an improved version of the epoll_create(). It creates a new epoll instance and returns the fd of that instance.

#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
  • epoll_ctl() is used to register new fds and add them to the interest list:

    • epfd epoll file descriptor
    • op the operation: EPOLL_CTL_ADD, EPOLL_CTL_MOD or EPOLL_CTL_DEL
    • fd the file descriptor to check
    • event a pointer to the epoll_event struct
  • epoll_wait() waits for I/O events, blocking the calling thread if no events are availables.

    • epfd epoll file descriptor
    • events array where there will be saved ready events
    • maxevents max events per array
    • timeout in milliseconds (-1 forever)
struct epoll_event {
    uint32_t events; // bitmap
    epoll_data_t data;
};

union epoll_data {
    void     *ptr;
    int       fd; // just use this
    uint32_t  u32;
    uint64_t  u64;
};