tcpdump本身不直接标注tcp重传包,需通过tcp标志位、序列号重复出现及时间戳比对等特征人工或脚本识别,重传是丢包、拥塞或接收方异常的信号而非孤立事件。

直接用 tcpdump 命令就能识别 TCP 重传包,关键不是“找重传”本身,而是理解重传出现的位置、频率和上下文——它往往是丢包、拥塞或接收方异常的信号,不是孤立事件。
用过滤表达式快速抓出重传包
tcpdump 本身不标“这是重传”,但可通过 TCP 协议特征精准筛选:
-
基础重传识别(推荐):
tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) == 0 and tcp[12:1] & 0xf0 == 0x50—— 过滤出非控制帧、含 ACK 且 TCP 头长为 80(即带时间戳选项),再结合序列号重复出现来人工比对 -
更实用的简化方式:先抓全量包(
sudo tcpdump -i eth0 -nn -s 0 -w retrans.pcap port 8080),再用tshark或 Wireshark 分析,或在命令行中用以下命令筛出疑似重传: -
tcpdump -r retrans.pcap -nn 'tcp[tcpflags] & tcp-ack != 0' | awk '{print $3, $NF}' | sort | uniq -c | sort -nr | head -10—— 统计高频出现的源IP:端口+序列号组合,重复次数多的极可能为重传 - 注意:
tcpdump默认不显示绝对序列号,加-S参数可启用(如tcpdump -S -r retrans.pcap),便于对比原始包与后续同 seq 的包
结合时间戳和连接上下文判断是否真重传
单看一个包无法确认是重传,必须放在完整 TCP 流中看:
- 用
tcpdump -r retrans.pcap -nn -tttt查看毫秒级时间戳,找同一连接(src/dst IP+port 相同)中相同序列号(seq)、不同时间点出现的包 - 典型重传模式:SYN 后 1 秒没回 SYN-ACK → 再发 SYN;或数据包发出后 200ms 无 ACK → 重发该 seq 数据
- 若看到连续多个
[TCP Retransmission]字样(Wireshark 打开后自动标注),说明内核已判定为重传;而 tcpdump 命令行输出里需靠人工或脚本比对 seq 和时间差
定位重传背后的真实原因
抓到重传只是第一步,重点是回答“为什么重传”:
- 网络层丢包:同一连接中同时出现大量重传 + 重复 ACK(Dup ACK),大概率是中间链路丢包(交换机过载、光衰、防火墙限速)
-
接收方问题:看到
Zero window advertised(Wireshark 专家信息中橙色警告)紧随重传之后,说明对端应用读取太慢,缓冲区满,导致无法 ACK,发送方只能重传 - 发送方异常:重传集中在某几个小范围 seq,且间隔极短(如 20ms 内连发 3 次),可能是网卡 offload(TSO/GSO)配置错误,或驱动 bug 导致分片失败
- 非重传误判:某些代理(如 Envoy/Nginx)在超时后主动 RST 连接,会触发客户端重传请求,此时要查 RST 包的发起方和时间点
生产环境高效排查建议
别等出问题才动手,提前建立轻量监控习惯:
- 用
tcpretrans工具(基于 eBPF)实时统计各连接重传数:sudo tcpretrans -L,支持按 PID、端口、状态过滤 - 写一行脚本定期采样:
sudo timeout 30 tcpdump -i eth0 -nn -s 0 port 8080 -w /tmp/$(date +%s).pcap 2>/dev/null &,配合定时任务保留最近 1 小时抓包 - 在微服务调用入口处(如 Sidecar 或 Nginx 日志旁)同步抓包,把重传时间与业务日志时间戳对齐,快速锁定是网络问题还是服务处理慢











