🌐Go deeper — read the bookTCP is a stream: framing & byte order— runnable code & full walkthrough →

sockets · advanced

OS: POSIX Sockets — TCP Server/Client, epoll, UDP, TCP_NODELAY, TIME_WAIT

POSIX TCP sockets. Server: socket(AF_INET,SOCK_STREAM,0) → setsockopt(SO_REUSEADDR) → bind() → listen(fd,backlog) → accept() → read/write → close. Client: socket() → connect() → read/write → close. htons()/ntohs(): host↔network byte order (big-endian) conversion for port and address fields. Non-blocking: fcntl(fd, F_SETFL, O_NONBLOCK); read returns EAGAIN when no data. Multiplexers: select O(n) 1024-fd limit; poll O(n) no limit; epoll O(1)/event Linux-only. epoll: epoll_create1→epoll_ctl(ADD)→epoll_wait; only ready fds returned. UDP: SOCK_DGRAM; no connection; sendto/recvfrom per packet; multicast for market data. SO_REUSEADDR: reuse port in TIME_WAIT state. TCP_NODELAY: disable Nagle algorithm for low latency. SO_RCVBUF/SO_SNDBUF: tune kernel buffer sizes. TIME_WAIT: 2*MSL after close; prevents stale packet corruption.

🔑 Key line

TCP sockets: socket→bind→listen(backlog)→accept; SO_REUSEADDR; htons() for endian; epoll for O(1) multiplexed I/O; TCP_NODELAY for low latency (disables Nagle); UDP: SOCK_DGRAM, sendto/recvfrom, no connection state.

The code

// POSIX Sockets — TCP client/server in C++
// TCP Server (minimal):
int fd = socket(AF_INET, SOCK_STREAM, 0); // create socket
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
struct sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(8080); // host-to-network-short (endian)
addr.sin_addr.s_addr = INADDR_ANY;
bind(fd, (sockaddr*)&addr, sizeof(addr));
listen(fd, 128); // 128 = backlog (max pending connections)
int client = accept(fd, nullptr, nullptr); // blocks until connection
write(client, "hello", 5);
close(client);
close(fd);
// TCP Client:
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in srv{};
srv.sin_family = AF_INET;
srv.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &srv.sin_addr);
connect(fd, (sockaddr*)&srv, sizeof(srv));
char buf[256];
read(fd, buf, sizeof(buf)); // receive
close(fd);
// Non-blocking I/O with select / epoll:
// select: O(n) per call; limited to FD_SETSIZE (1024) fds
// poll: O(n) per call; no fd limit
// epoll: O(1) per event; Linux only; production standard
int epfd = epoll_create1(0);
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
struct epoll_event events[64];
int n = epoll_wait(epfd, events, 64, -1); // block until events
for (int i = 0; i < n; i++) {
if (events[i].data.fd == listen_fd) { /* new connection */
} else { /* data to read on events[i].data.fd */
}
}
// UDP (connectionless):
int fd = socket(AF_INET, SOCK_DGRAM, 0);
// no connect/listen/accept — just sendto/recvfrom
sendto(fd, data, len, 0, (sockaddr*)&dst, sizeof(dst));
recvfrom(fd, buf, sizeof(buf), 0, (sockaddr*)&src, &srclen);
// Key options:
// SO_REUSEADDR: reuse port after crash (avoids TIME_WAIT)
// TCP_NODELAY: disable Nagle algorithm (for low-latency)
// SO_RCVBUF / SO_SNDBUF: tune kernel buffer sizes
// O_NONBLOCK: non-blocking I/O (use with epoll)

What this lesson walks through

  1. 01TCP 3-way handshake and socket lifecycle
  2. 02TCP server — minimal C++ implementation
  3. 03epoll — O(1) multiplexed I/O for production servers
  4. 04UDP and key socket options
  5. 05Non-blocking sockets and select/poll comparison
  6. 06Socket interview patterns — common questions

TCP connection: SYN → SYN-ACK → ACK (3-way handshake). Socket lifecycle: socket() creates a file descriptor. bind() assigns local address/port. listen() marks it passive (server). accept() blocks until client connects — returns a NEW fd for that connection. The original fd stays listening for more connections. connect() initiates connection (client side). read()/write() for data transfer. close() sends FIN.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of OS: POSIX Sockets — TCP Server/Client, epoll, UDP, TCP_NODELAY, TIME_WAIT and 100+ animated C++ interview lessons.

← Previous
IPC: Signals & sigaction — Async Notifications, Masks, and Handler Safety
Next →
Sockets: TCP vs UDP