首页/系统/Linux 内核与性能调优速查/SO_LINGER 与主动 RST 关闭
网络栈调优98 条

SO_LINGER 与主动 RST 关闭

SO_LINGER 控制 close 时未发送数据的行为: 超时归零可立即以 RST 关闭, 常规关闭则尽力发送。

关闭行为控制

SO_LINGER 控制 close 如何处理发送缓冲区中尚未确认的数据。默认状态下 close 立即返回,剩余数据由内核异步发送;开启并把等待时间设为 0 时,close 会丢弃未发送数据并发出 RST,连接被强制终止。它常用于需要立刻释放文件描述符与本地端口的场景,代价是对端可能收到重置而不是正常结束。

基本信息

适用平台Linux / Unix 通用套接字选项
常用取值开启且等待 0 秒即强制重置;等待大于 0 秒则阻塞等待发送
权限要求普通用户即可
核心取舍释放越快,越可能丢数据

典型使用场景

  • 短连接代理需要立刻回收描述符与本地端口,避免大量等待关闭状态占用资源。
  • 业务已确认可以丢弃剩余响应(如上游已放弃的请求),希望快速结束而不是慢速挥手。
  • 排查对端报连接被重置的问题,确认本端代码是否设置了立即关闭。
  • 模拟异常断链,验证客户端重连与幂等逻辑。
  • 压测中控制连接生命周期,避免测试机端口耗尽影响下一轮。

C 用例

C 用例
struct linger lg = { .l_onoff = 1, .l_linger = 0 };   /* 开启并立即关闭 */
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lg, sizeof(lg)) < 0) {
    perror("setsockopt SO_LINGER");
}
close(fd);   /* 丢弃发送缓冲未确认数据,发出 RST */

关闭行为对比

配置close 行为对端结果
默认关闭该选项立即返回,内核继续发送缓冲数据正常结束,数据较完整
开启且等待 0 秒丢弃缓冲数据,发出重置连接被重置,未读数据丢失
开启且等待若干秒最多阻塞等待若干秒数据较完整,但调用线程被占用
重置关闭不经过正常挥手,对端未读到的数据会被丢弃;HTTP 场景里客户端往往报连接被重置,而不是正常结束。
不要为了掩盖描述符泄漏或端口耗尽而统一开启立即关闭:真正的根因通常在连接管理,强制重置只会把问题转移到业务侧的随机失败上。

易错点

  • 滥用立即关闭让对端收到重置:客户端可能报连接重置、日志出现未完成请求,表现为随机失败且难以复现。
  • 忽略发送缓冲中未确认数据被丢弃:响应体较大时用户会看到内容截断,且服务端日志显示成功。
  • 设置较长等待时间后让 close 阻塞:工作线程被挂住,吞吐下降甚至引发超时级联。
  • 以为它能解决等待关闭状态堆积:重置关闭的一方确实不进入该状态,但代价是数据可靠性,属于用语义换资源。
  • 排查连接重置时先怀疑网络设备:内核参数与抓包都正常时,答案往往在应用层有没有设置过这个选项。

数据来源与参考

  • man 7 socket
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌