Sockets & Network Programming

a blocking socket

Imagine standing at a mailbox waiting for a letter and refusing to do anything else — not even blink — until one arrives. That is blocking behavior. By default, a socket is blocking: when you call recv and no data has arrived yet, the call simply waits, and your program is frozen at that line, doing nothing, until either some bytes show up or the connection closes. Likewise, a blocking send waits if the kernel's send buffer is full.

More precisely, a blocking call puts your thread to sleep and the operating system wakes it only when the operation can make progress. This is wonderfully simple to reason about: you write straight-line code — connect, send the request, recv the reply — and each step finishes before the next starts. The cost is that one thread can attend to only one socket at a time. If you call recv on a quiet connection, that thread cannot also be reading a busy one. accept and connect block too: a blocking accept sleeps until a client arrives.

Why it matters: blocking sockets are the natural, readable default, and for a client talking to one server, or a server that gives each connection its own thread or process, they are exactly right. The trouble comes when one thread must serve many connections: a single blocking recv on an idle client stalls everyone behind it. The answers are either concurrency (a thread or process per connection, which costs memory and context-switching) or switching the sockets to non-blocking mode and using I/O multiplexing (select, poll, epoll) so one thread can watch many sockets and act only on the ones that are ready — the event-loop model behind high-performance servers like Nginx.

A server with one thread calls recv on client A, who sends nothing for a minute. The thread sleeps the whole minute. Clients B and C, ready to talk, are ignored — because the single thread is blocked on A. This is exactly the trap I/O multiplexing solves.

Simple to read, but one blocked call stalls everything behind it.

Blocking is not bad — it is the simplest correct model when each connection has its own thread or process. It only becomes a problem when you try to serve many connections from one thread without multiplexing.

Also called
blocking I/Osynchronous I/O阻塞式 I/O同步 I/O