TCP 实战与排错 — 抓包、观测与故障定位

TCP Wireshark 抓包、ss/netstat 状态、TIME_WAIT 堆积/重传高/建连失败排查、与 UDP 对比 / 传输层 / RFC 9293

这篇你能学到

  • 用 Wireshark 过滤式快速锁定握手失败、重传、重复 ACK、RST 和零窗口这几类关键现象。
  • ss / netstat 从系统侧看连接状态分布、每连接 RTT 与 cwnd,以及几个常用内核调优项。
  • 六类高频故障(SYN 无响应、TIME_WAIT 堆积、重传率高、吞吐上不去、RST 频发、建连慢)的结论先行式排查,外加对比表和面试速查。

1. 抓包观察

下面这些过滤式的作用:从一堆 TCP 流量里,分别把"握手首包"“重传"“重复 ACK"“异常复位"“对端收不动了"这几类现象单独挑出来——排障基本就是围绕这五件事展开。

过滤式作用
tcp / ip.proto == 6所有 TCP
tcp.flags.syn == 1 && tcp.flags.ack == 0只看 SYN(握手首包)
tcp.analysis.retransmission重传段
tcp.analysis.duplicate_ack重复 ACK(可能触发快速重传)
tcp.flags.reset == 1RST(异常断开)
tcp.analysis.zero_window接收窗口为 0(对端繁忙)

这三条命令分别干什么:第一条带绝对时间戳和绝对序号抓 443 端口流量,适合看时序;第二条只抓 SYN,用来确认握手请求到底有没有发出/到达;第三条从本机视角快速列出当前 TCP 连接及其所属进程。

1
2
3
tcpdump -i eth0 -nn 'tcp port 443' -tttt -S
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0' # 仅 SYN
ss -tanp | head

Wireshark 中 Follow → TCP Stream 可重组字节流;IO Graph 看吞吐与重传率。

2. 常用命令 / 观测

这几条命令分别干什么:第一条统计各 TCP 状态各有多少连接(一眼看出是不是 TIME_WAIT 或 CLOSE_WAIT 堆积);第二条看每条连接的 RTT、cwnd、重传等内部指标;第三条看系统级累计重传数;后两条是临时的内核调优——分别开启客户端 TIME_WAIT 复用和放大接收缓冲上限。

1
2
3
4
5
6
ss -tan | awk '{print $1}' | sort | uniq -c # 各状态连接计数
ss -tni # 每连接 RTT、cwnd、重传
netstat -s | grep -i retransmit # 系统级重传统计
# 内核可调(临时)
sysctl -w net.ipv4.tcp_tw_reuse=1 # TIME_WAIT 复用(客户端)
sysctl -w net.core.rmem_max=16777216 # 增大接收缓冲

3. 常见故障与排错

现象:SYN 无响应

先记住结论: 先别怀疑 TCP 本身——要么对端根本没在监听,要么中间被防火墙静默丢弃,要么后端已经过载。

排查/解决:ss -lnt 查 LISTEN;抓包看 SYN 是否到达、是否回 SYN+ACK。

现象:大量 TIME_WAIT

先记住结论: 这通常不是故障,而是"你是主动关闭方 + 短连接高并发"的必然结果。

排查/解决:连接复用/长连接;tcp_tw_reuse(客户端);tcp_max_tw_buckets

现象:重传率高

先记住结论: 重传是结果不是原因,真正的病根在丢包、链路拥塞或缓冲膨胀上。

排查/解决:tcp.analysis.retransmission 定位;查 RTT、丢包;换 BBR。

现象:吞吐上不去

先记住结论: 带宽没跑满,多半是窗口被卡住了——rwnd/cwnd 受限,或者窗口缩放选项压根没开。

排查/解决:看 Window Scale 选项;增大缓冲;BBR。

现象:RST 频发

先记住结论: RST 是"对方明确拒绝或已不认这条连接”,先找出是谁发的。

排查/解决:抓 RST 来源;查服务状态与 backlog。

现象:连接建立慢(SYN 队列满)

先记住结论: 请求到了但排不上队——半连接/全连接队列已满。

排查/解决:调大半/全连接队列。

现象原因排查/解决
SYN 无响应对端未监听 / 防火墙 DROP / 后端过载ss -lnt 查 LISTEN;抓包看 SYN 是否到达、是否回 SYN+ACK
大量 TIME_WAIT短连接高并发(主动关闭方)连接复用/长连接;tcp_tw_reuse(客户端);tcp_max_tw_buckets
重传率高网络丢包 / 链路拥塞 / 缓冲膨胀tcp.analysis.retransmission 定位;查 RTT、丢包;换 BBR
吞吐上不去rwnd/cwnd 受限、窗口缩放未开看 Window Scale 选项;增大缓冲;BBR
RST 频发端口无服务、半开连接、应用崩溃抓 RST 来源;查服务状态与 backlog
连接建立慢(SYN 队列满)tcp_max_syn_backlog 不足调大半/全连接队列

4. 与其他协议对比

维度TCPUDP
连接面向连接无连接
可靠是(重传/确认)
消息边界无(字节流)有(数据报)
拥塞/流控有(cwnd/rwnd)
头部20+ 字节8 字节
适用文件/网页/SSH视频/游戏/DNS/QUIC

5. 速查表 / 常见面试题

项目
RFC / IP 协议号RFC 9293 / 6
MSS(典型)1460
握手 / 挥手3 次 / 4 次
TIME_WAIT2MSL(Linux 60s)
重传触发RTO 超时 / 3 个重复 ACK
窗口rwnd(流控)+ cwnd(拥塞)
  • Q:为什么握手 3 次、挥手 4 次? 握手 SYN+ACK 可合并;挥手时被动方收到 FIN 后可能还有数据要发,故 ACK 与 FIN 分开。
  • Q:TIME_WAIT 意义? 确保最后 ACK 到达对端、让网络中残留旧报文失效,避免新连接误收。
  • Q:TCP 为什么会粘包? TCP 是字节流无消息边界,“粘包"是应用层未分帧,需在应用层加长度前缀/分隔符。
  • Q:快速重传 vs 超时重传? 收 3 个重复 ACK 即重发(进快速恢复);RTO 超时则回慢启动,后者代价大。
  • Q:CUBIC 与 BBR 区别? CUBIC 基于丢包做拥塞信号(Reno 演进);BBR 基于带宽-时延积建模,抗缓冲膨胀。