首页/网络/抓包与流量分析速查/RST 关闭与 SO_LINGER
TCP 流分析82 条

RST 关闭与 SO_LINGER

应用设置 SO_LINGER=0 时 close 直接发 RST:跳过挥手、丢失未确认数据;抓包表现为数据后紧跟 RST,排查"数据截断"时要想到它。

RST 关闭是什么

应用把套接字选项 SO_LINGER 设为开启且超时为零后,close() 不再走四次挥手,而是直接发出 RST 结束连接,发送缓冲区里尚未被确认的数据随之丢弃。抓包表现是一段数据之后紧跟 RST,既没有 FIN,也没有对端的确认。这种写法多见于高并发短连接服务、连接池的空闲连接回收逻辑,以及错误分支里“立刻断开”的实现。排查“数据截断”“对端少收一段”类问题时应当优先怀疑它,因为协议不再保证已写出的数据被对方处理。

基本信息

触发条件SO_LINGER 开启且 l_linger 为 0
报文形态无 FIN,数据或 ACK 之后直接 RST
抓包字段tcp.flags.reset == 1
协议影响未确认数据被丢弃,对端通常报 connection reset
排查对象应用框架、连接池与网关的连接回收实现

典型使用场景

  • 数据截断排查:对端只收到部分数据且以连接重置结束,需要确认发送侧是否强制关闭
  • 连接池核查:确认池在回收空闲连接时是否使用强制关闭,以及回收时机是否在写操作之后
  • 短连接优化:减少四次挥手开销的常见手段,需要评估数据丢失风险
  • 设备侧影响评估:RST 会被部分安全设备记为会话异常终止,影响告警统计
  • 关闭方式统计:观察正常 FIN 关闭与 RST 关闭的比例变化

观察与设置

观察与设置
tcp.flags.reset == 1 && tcp.len == 0    # 定位无数据的 RST 报文
# 判据:数据段之后紧跟由发送方发出的 RST
# Linux 上设置强制关闭(示意,字段名以平台为准)
# struct linger {int l_onoff; int l_linger;}  l_onoff=1, l_linger=0

关闭方式对照

关闭方式报文序列数据保证
正常关闭FIN、ACK,对端 FIN、ACK内核重传未确认数据直到成功或超时
强制关闭直接 RST,无 FIN缓冲区中未确认数据被丢弃
重传耗尽后放弃连续重传后发出 RST放弃时刻仍未确认的数据丢失
服务端发出 RST 也可能是协议规定的兜底响应:进程重启后收到属于旧连接的数据包时,会回 RST 告知对端该连接不存在,这种情况不代表应用做了强制关闭。
判断时先确认 RST 的发出方向以及它相对最后一个数据报文的位置:数据之后紧跟本端 RST,才是强制关闭的典型特征。

易错点

  • RST 之前已经写出的数据不保证被对端读取,业务上不能把写成功当成对方已处理,需要应用层确认机制兜底
  • 抓到连接重置时先分清是本端强制关闭还是对端重启后回的 RST,两者的排查方向完全相反
  • 用强制关闭回收连接能省掉挥手开销,但在有未发送数据的路径上会静默丢数据,压测覆盖不到的长尾场景最容易暴露
  • Windows 与 Linux 对 linger 结构体的字段定义存在差异,跨平台代码直接套用可能设置无效,先确认平台实现再下结论

数据来源与参考

  • Linux socket 文档(SO_LINGER)
  • RFC 9293(RST)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌