地址复用选项
SO_REUSEADDR 是套接字选项,让 bind 在本地地址仍处于等待关闭状态时可以继续绑定,避免服务重启瞬间报地址已被占用。它只影响地址复用,不改变连接建立流程,也不允许多个进程同时监听同一端口。多数服务器框架在监听前都会设置它:Go 的监听默认开启,Java 的 ServerSocket 默认值为真,C 程序需要自己显式设置。
基本信息
| 适用平台 | Linux / Unix;Windows 同名选项语义不同 |
|---|---|
| 设置时机 | 必须在 bind 之前调用,否则不生效 |
| 解决现象 | 重启时报地址已被占用 |
| 常见默认 | Go、Java 等监听默认开启,C 程序需自己设置 |
| 易混淆项 | SO_REUSEPORT 才支持多进程同端口并发监听 |
典型使用场景
- 服务滚动重启时,避免上一进程遗留的等待关闭地址挡住新进程绑定。
- 进程被强制终止后立即拉起同端口的服务,不想等待超时结束。
- 开发机频繁启停同一端口的调试服务,热重载框架尤其明显。
- 确认它只用于地址复用,而不是用来做多进程负载分担。
- 跨平台移植时核对 Windows 上的同名选项语义差异。
C 用例
C 用例
int one = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
perror("setsockopt SO_REUSEADDR"); /* 必须在 bind 之前设置 */
}
bind(fd, addr, addrlen);验证是否解决
验证是否解决
ss -tan state time-wait | head # 先确认等待关闭的连接规模
ss -lntp | grep 8080 # 确认端口已被新进程成功监听
systemctl restart app && ss -lnt 'sport = :8080' # 反复重启做一次验证两个选项的分工
| 选项 | 作用 | 适用场景 |
|---|---|---|
| SO_REUSEADDR | 允许在地址处于等待关闭状态时绑定 | 单进程监听、需要快速重启 |
| SO_REUSEPORT | 允许多个套接字绑定同一地址端口 | 多进程各自接受连接的部署 |
| 叠加使用 | 语义不同,可同时设置 | 按部署模式决定是否都需要 |
它解决的是地址重用而非端口独占:想让多个进程共同监听同一端口必须用 SO_REUSEPORT,且各套接字的属主权限需要一致。
Windows 上同名选项的语义是允许其他进程抢占已监听的端口,与 Linux 相反;跨平台代码不要照搬这段设置。