关闭之后再收到数据会怎样
TCP 连接一旦进入关闭流程,某一方向已经发出 FIN 并得到确认后,这个方向上的数据传输就结束了。如果此时仍然收到该方向的数据或迟到的旧报文,接收方会直接回一个 RST,告诉对端这条连接已经不存在。抓包顺序表现为 FIN 确认之后跟着一个 RST。这是协议定义的正常保护行为,通常由内核发出,与进程是否崩溃没有必然关系。
基本信息
| 典型顺序 | FIN → ACK → 对端继续发数据 → RST |
|---|---|
| 过滤表达式 | tcp.flags.fin == 1 || tcp.flags.reset == 1 |
| 发出方 | 通常由内核协议栈保护性发出,不代表应用进程异常 |
| 涉及状态 | 半关闭、等待关闭、等待超时回收等状态转换 |
| 判断要点 | 看数据是否在关闭之前已被接收方确认 |
| 常见诱因 | 应用提前关闭、对端不知道连接已结束、中间设备回收了连接 |
典型使用场景
- 数据丢失排查:确认业务发出的数据是否在连接被关闭后才到达,解释响应丢失
- 误报澄清:应用日志把 RST 记为异常断开,实际是关闭后的正常保护
- 超时核对:一方已超时关闭而另一方仍在写,导致连接被复位
- 中间设备排查:负载均衡或防火墙回收了空闲连接,两端感知不一致
- 协议讲解:用抓包演示半关闭状态下各方的行为
定位关闭时序
定位关闭时序
# 只看某条连接的关闭相关帧, 按时间顺序排列
tshark -r a.pcap -Y 'tcp.stream == 7 && (tcp.flags.fin == 1 || tcp.flags.reset == 1)' \
-T fields -e frame.number -e frame.time_relative -e ip.src -e ip.dst -e tcp.flags.str
# 找出全文件里所有关闭后复位的组合
tshark -r a.pcap -Y 'tcp.flags.reset == 1' -T fields -e frame.number -e tcp.stream -e _ws.col.info | head -20
# 确认关闭前数据是否已被确认(看 ACK 是否覆盖了最后一个数据序号)
tshark -r a.pcap -Y 'tcp.stream == 7' -T fields -e frame.number -e tcp.seq -e tcp.ack -e tcp.len | tail -20复位场景对照
| 场景 | 抓包表现 | 含义 |
|---|---|---|
| 关闭后收到迟到数据 | FIN 确认后紧跟 RST | 协议正常保护, 无需修复 |
| 应用提前关闭 | 请求发出后很快关闭 | 应用侧读取超时或逻辑提前结束 |
| 一方超时回收 | 长时间空闲后出现 RST | 超时参数两端不一致 |
| 中间设备回收连接 | RST 来自非对端地址 | 负载均衡或防火墙清理了会话 |
| 端口未监听 | 连接建立阶段就被 RST | 与关闭后复位不是同一类问题 |
这个 RST 通常由内核发出,含义是「这条连接已经没有了」,排查数据未被处理的问题时应回看关闭时序与数据确认情况,而不是去查进程崩溃。
对迟到数据回 RST 是标准行为,不需要修复;需要关注的是为什么关闭发出后还有数据在路上,通常是两端超时或关闭时机不一致。