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,才是强制关闭的典型特征。