TCP 流分析82 条

TCP 同时关闭判读

双方几乎同时发 FIN 时进入同时关闭流程(各回 ACK 后等待对方 FIN):抓包表现为两侧 FIN 交叉,属正常协议路径而非异常。

双方同时关闭会发生什么

正常关闭是一条四次挥手:一端先发 FIN,另一端确认后再发自己的 FIN。如果双方几乎同时决定结束,就会出现同时关闭:各自发出 FIN,各自确认对方的 FIN,随后两条方向分别走完关闭流程。抓包的表现是两侧的 FIN 在时间上很接近,互相交叉,而不是先关完一头再关另一头。这是状态机里定义好的正常分支,不是异常断连。

基本信息

抓包表现两侧 FIN 时间接近,各自发出并被对方确认
典型顺序A 发 FIN 的同时 B 也发 FIN,双方各自回 ACK 后完成关闭
状态变化两端分别经历发出 FIN、收到确认、等待对端 FIN、最终关闭
高发场景对称协议、双方同时判断任务结束的场景
少见原因常见的请求响应模型通常是一端先关,出现概率较低
排查前提多点抓包时需对齐时钟,中间设备可能只看到单向 FIN

典型使用场景

  • 误报澄清:把交叉 FIN 从「异常断开」里排除,避免误判应用崩溃
  • 协议讲解:用实际抓包展示状态机的非典型分支
  • 中间设备排查:确认防火墙或负载均衡是否正确转发了双向的 FIN
  • 日志对齐:把两侧日志里的关闭时间与抓包交叉验证
  • 连接回收分析:确认连接是自然关闭还是被复位,为资源统计提供依据

看两侧 FIN 的时间关系

看两侧 FIN 的时间关系
# 列出所有 FIN, 按时间排序, 观察是否成对出现
tshark -r a.pcap -Y 'tcp.flags.fin == 1' -T fields -e frame.number -e frame.time_relative -e ip.src -e ip.dst -e tcp.stream | head -30
# 只看某条连接的关闭过程
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 tcp.flags.str
# 两端分别抓包时, 先确认两侧时钟已对齐再比对
tshark -r client.pcap -Y 'tcp.flags.fin == 1' -T fields -e frame.number -e frame.time -e ip.src

关闭流程对照

情形抓包特征判读
正常四次挥手一端 FIN, 另一端先 ACK 后 FIN最常见, 无异常
同时关闭两端 FIN 交叉出现正常分支, 不是断连
一端复位出现 RST 而非 FIN 交互需要结合应用行为判断
中间设备只转发单向 FIN一端看到 FIN, 另一端看不到检查设备对双向 FIN 的转发
一端先超时回收另一端的写操作触发复位超时参数两端不一致
出现同时关闭不必修复:它只是状态机的一条合法路径。真正需要关注的是关闭之后的复位,以及两端对关闭时机的理解是否一致。
跨设备抓包比对关闭时序前先对齐时钟,否则相隔几毫秒的两条 FIN 会被看成相隔几分钟,得出完全错误的先后关系。

易错点

  • 把交叉出现的 FIN 判定为异常断连,进而在应用层找崩溃原因,而实际上链路是正常关闭的
  • 多点抓包未对齐时钟就比对关闭时间,两端的先后顺序被误读,因果推断错误
  • 把同时关闭与关闭后被复位混为一谈,前者是正常分支,后者才提示连接被提前回收
  • 只看单点抓包就断言双向关闭过程,中间设备若只转发了一侧的 FIN,另一端的行为完全看不到

数据来源与参考

  • RFC 9293(同时关闭)
  • Wireshark User's Guide
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌