the accept loop and SO_REUSEPORT
/ accept -> ak-SEPT; SO_REUSEPORT -> ess-oh REUSE-port /
A server that takes connections has a doorway and a greeter. The doorway is a listening socket - you bind() it to a port and listen() on it. The greeter is the accept loop: a cycle that calls accept(), which hands back a brand-new connected socket for each client that arrives, while the listening socket itself stays open to greet the next one. Everything a multi-connection server does begins with this loop turning new arrivals into per-connection descriptors.
The basic loop is: for(;;) { int conn = accept(listen_fd, ...); handle(conn); }. In a non-blocking, event-loop server you instead watch listen_fd for readability and call accept() until it returns EAGAIN, draining all pending connections. The scaling problem is that with one listening socket shared by many worker threads, they contend on it and suffer thundering-herd wakeups. SO_REUSEPORT is the fix: it is a socket option that lets MULTIPLE sockets bind() to the very same port at once. You give each worker its own listening socket on the shared port, and the kernel hashes each incoming connection to exactly one of them. Now workers never contend on a single accept point - each has a private queue the kernel fills.
Why it matters: SO_REUSEPORT turns the accept path from a contended bottleneck into clean, kernel-driven load distribution across cores, and it allows graceful restarts (a new process can bind the port before the old one exits, so no connection is refused). The honest caveats: the kernel's distribution is by a hash, not by which worker is least busy, so a worker stuck on a slow request can still have new connections queued behind it; and a listening socket closing can briefly disrupt the connections the kernel had already steered into its queue, which matters during restarts.
int s = socket(AF_INET, SOCK_STREAM, 0); int one = 1; setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof one); bind(s, addr, addrlen); listen(s, 1024); /* each worker does this on the same port */
With SO_REUSEPORT set, each worker binds its own listening socket on the shared port and the kernel spreads connections across them.
Do not confuse SO_REUSEPORT with SO_REUSEADDR: SO_REUSEADDR mainly lets you re-bind a port stuck in TIME_WAIT after a restart, while SO_REUSEPORT lets multiple live sockets share one port for load distribution. The kernel spreads connections by hash, so it is not the same as routing to the least-loaded worker.