weichengyi.com

SO_REUSEADDR is not SO_REUSEPORT

2 May 2025 · networking

They get used interchangeably in blog posts and they should not be.

SO_REUSEADDR

Lets a socket bind an address that still has sockets lingering in TIME_WAIT from a previous process. That is the option that makes a server restartable without waiting out the 2×MSL timer and seeing EADDRINUSE for a minute. It does not let two live listening sockets share a port.

SO_REUSEPORT

Does exactly that. Several sockets, each having set the option before binding, share one address and port, and the kernel distributes incoming connections across them by hashing the connection 4-tuple. It is how a multi-process server accepts in parallel without a shared listening socket, and it avoids the thundering herd that a single shared descriptor produces.

The traps

Every socket in the group must set the option — if one forgets, it gets EADDRINUSE instead of joining. On Linux they must also share an effective UID, which exists specifically so a different user cannot quietly join a group and steal traffic from a port already in use.

And the load balancing is per-connection, not per-byte. A hash on the 4-tuple distributes connections evenly in aggregate but says nothing about how much work each one carries, so a worker that draws several long-lived heavy connections stays busy while its siblings idle. If your connections are long-lived and unequal, SO_REUSEPORT is not the load balancer you wanted.