Wireshark实战:用TCP报文解析三次握手与拥塞控制
2026/9/15 4:49:49 网站建设 项目流程

说句实话,很多学过计网的同学都会有同一种感觉:教材翻完一遍,概念都认识,但真要打开 Wireshark 去看 TCP 连接,又不知道该点哪里。这一系列内容,就是想把“自顶向下”的思路落到实际操作上。如果你是第一次看到这个系列,可以把它理解成《计算机网络:自顶向下方法》的配套学习笔记,更多是站在动手实验的角度,把应用层、传输层这些抽象概念一个一个拉回到真实的报文里。比如《计网自顶向下(2)》这一篇,主角就是 TCP 和一份非常经典的流量包:wireshark-traces-9e.zip 里的 tcp-wireshark-trace-1.pcap。建议配合教材第 9 版的 TCP 实验一起看,适合正在啃计网课程、准备考研复试、或者刚入行做网络排查的读者。看完这一篇,你会对三次握手、序列号、确认号、重传、拥塞控制这些名词有一个完全不同的感觉,因为它们不再只是课本上的黑体字,而是能在报文列表里一个个点出来、对上号的东西。

1. 自顶向下视角与第二部分的内容布局

1.1 为什么从应用层出发而不是物理层

传统网络教学喜欢从物理层讲起,双绞线、集线器、交换机、路由器一层层往上搭。这样不是不行,但问题在于,学完物理层和数据链路层,很多人根本不知道这一章和“打开网页”有什么关系。自顶向下的思路反过来:先承认一个事实——绝大多数人学网络,是为了理解应用程序怎么通信,比如浏览器怎么把请求发出去、视频通话为什么有时候卡、服务器为什么连不上。

这个视角在第二部分体现得特别明显。第一部分一般停留在应用层,讲 HTTP、DNS、SMTP 这些协议,让你知道“应用之间在说什么”。到了第二部分,就到了传输层,回答一个更底层的问题:“这些消息到底是怎么在网络上可靠地传过去的?”这个问题的核心就是 TCP。从应用层的视角往下走,你会发现,TCP 的所有机制——握手、确认、重传、拥塞控制——都不是凭空设计出来的,它们全是为了服务上层应用的需求。

我特别想强调一个点:很多初学者把 TCP 当成一个“可靠传输协议”就完事了,但可靠并不是免费的。TCP 为了完成可靠传输,付出了报文头开销、连接建立开销、拥塞控制带来的带宽让步这些代价。所以第二部分的内容里,你既要看到 TCP 做了什么,更要看到它为什么非做不可。带着这个问题去看 tcp-wireshark-trace-1.pcap 里的报文,就会顺很多。

1.2 第二部分的坐标:传输层和服务模型

传输层位于应用层和网络层之间,这一层有两个核心协议:UDP 和 TCP。很多教材习惯用表格去对比它俩,一个面向连接、一个无连接,一个可靠、一个不可靠,一个慢、一个快。但实际理解时,我建议换个角度:UDP 是对 IP 服务模型的最小扩展,它只加了端口号,用来标识进程,其他“可靠性”一概不管;TCP 则是在 IP 之上重新实现了一套可靠字节流服务,把乱序、丢包、重复这些问题都处理掉。

理解这个坐标特别关键,因为自顶向下方法并不是说只看上层,而是说从上层需求出发,再逐层理解下层的设计。比如你点开一个网页,HTTP 要求的是“请把这段 HTML 完整地、按顺序地给我”,应用层不管底下怎么做,它只管把请求交给传输层。这时 TCP 就得想尽办法满足这个需求。但如果是一个实时语音通话,应用要求的是“低延迟第一,丢几个包无所谓”,这时候 UDP 反而是更合适的选择。所以说,二层目录里 TCP 和 UDP 的对比,本质上是对应用需求的两种回答。

这个阶段容易忽略的是传输层还有个职责:多路复用和多路分解。一个主机上同时跑着微信、浏览器、邮件客户端,网络层收到一个报文后怎么知道该交给哪个进程?就是靠端口号。这也解释了为什么你在 Wireshark 里会看到源端口 443、目的端口 5201 这种奇怪的数字组合。它们不是随便出现在那儿的,它们就是多路分解的钥匙。

1.3 TCP 与 UDP 的关键对照

既然第二部分重点是 TCP,我先把两个协议的关键差异放在这儿,作为后面看包的基础。这个对照表不是从教材抄的,是你抓包之后能亲眼验证的。

对比维度UDPTCP
连接状态无连接,发完即走面向连接,三次握手建立连接
可靠性不保证不丢包、不保证顺序通过 ACK、重传、序列号保证可靠有序
流量控制通过接收窗口字段实现端到端流量控制
拥塞控制通过拥塞窗口、慢启动、拥塞避免等机制控制
报文开销8 字节头部20 字节以上头部,选项字段可变
适用场景DNS、音视频实时通信文件传输、网页访问、邮件

这张表里最容易让人忽略的是“连接”到底是什么。TCP 的连接不是一个实体的电路,而是一组状态:双方各自维护序列号、窗口大小、拥塞状态。连接在报文里看不到,它是通信两端为这次通信专门建立的一套“记忆”。所以三次握手的本质,就是让双方交换初始序列号,这套记忆从哪开始,只有双方知道。后面看握手包时你可以留意,SYN 报文里带的序列号完全不是从 0 或者 1 开始的,往往是一个很大的随机数,这就是因为初始序列号是双方各自定的,对方需要拿到这个数才能确认后续数据。

2. Wireshark 实验资源与实验前准备

2.1 wireshark-traces-9e.zip 和 tcp-wireshark-trace-1.pcap 是什么

如果你用的是《计算机网络:自顶向下方法》第 9 版,应该知道这本书配套的实验手册里会给一堆抓包实验,其中 TCP 实验用到的就是这个 tcp-wireshark-trace-1.pcap。所有的 trace 文件统一打包在 wireshark-traces-9e.zip 里。你不需要自己先去抓包,就能直接分析一段真实的 TCP 流量。这个文件对新手特别友好,因为它是从真实网络环境中抓下来的 TCP 传输过程,里面能看到完整的连接建立、数据传输、连接关闭,甚至可能包含重传或乱序的情况。

我看到不少人拿到这个压缩包之后,习惯性双击点开 pcap,结果满屏几百条 TCP 报文,瞬间懵了。这里有个非常实用的原则:不要用看邮件的心态看 pcap,要用查档案的心态。你不需要从头到尾读每一包,你要做的是先在大脑里画出一个 TCP 生命周期:连接建立(三次握手)→ 数据传送 → 连接关闭(四次挥手)。然后带着这个框架,去报文里找对应的位置。这样 pcap 就不是一堆杂乱报文的堆积,而是一个可被拆解的流程故事。

如果纯粹只是为了完成实验作业,很多人会直接把 Wireshark 打开,点“文件→打开”,选中这个 pcap,然后开始答题。但我建议你额外做一件事:打开之后先把所有报文按“时间”排好序,然后用着色规则看一遍全局,你会发现不同阶段的报文在颜色上有明显区分。这不是花架子,它能帮你快速抓住整个捕获文件的大致节奏,比如哪段时间是高速传输,哪段时间是空窗期。

2.2 Wireshark 环境准备和基础过滤

Wireshark 本身安装没什么好讲的,下载对应系统版本,默认安装,装完记得装 Npcap 或者 WinPcap 的抓包驱动,不然你无法捕获实时数据包。但这里有个容易踩的坑:只分析 pcap 文件时,其实不需要抓到本地网卡的数据,也可以分析。很多人误以为必须联网才能做实验,其实打开一个已有的 pcap,Wireshark 完全离线可用,这一点在实验室或机场无线网络比较不稳的环境下非常管用。

打开 tcp-wireshark-trace-1.pcap 之后,第一件事就是设置过滤表达式。Wireshark 有两种过滤:捕获过滤和显示过滤。我们现在分析已存在的文件,只需要用显示过滤。最常用的三个:

  • tcp:只看 TCP 报文。
  • tcp.flags.syn==1:只看包含 SYN 标志的报文。
  • tcp.stream eq 0:只看第一条 TCP 流。

tcp.stream eq 0这个过滤是我想重点强调的。一个 pcap 里可能包含好多条 TCP 连接,每条连接都算是一个流。如果不加限制,几百个包混在一起特别乱。先过滤出第一条流,你就能看到一个完整、独立的 TCP 连接过程。这比从头到尾硬看几百个包要高效得多。

要注意,Wireshark 的过滤语法对大小写敏感,字段名错了不会报错,只是结果为空。比如你把tcp.flags.syn写成tcp.flags.Syn,它会提示你有问题或者直接给空结果。排查的时候先检查这些细节,免得误以为文件有问题。

2.3 先读 pcap 再抓包:更稳定的学习路径

很多同学一上来就想抓自己的包,比如抓一个访问网页的 flow,然后用它来分析。这种做法精神可嘉,但实际执行起来经常翻车:浏览器开了 HTTP/2、连接复用、TLS 加密,打开一个页面的流量里能看到一堆 TCP 流,但大多数内容是加密的,没法直观对上应用层的请求和响应。而且自己抓包还容易抓进其他后台流量,分析起来噪声很大。

我强烈建议的学习路径是,先把课程提供的 tcp-wireshark-trace-1.pcap 研究明白,再做自己的抓包实验。它相当于“标准答案”,你能用它对好坐标,知道一个正常的 TCP 流应该长什么样。在自己抓包之前,你已经建立了对正常行为的判断基准,后面看到任何异常都有对比的对象。如果跳过这个基准直接抓自己的包,很容易陷入“每个包看着都像那么回事,但又不知道哪个才是重点”的迷茫里。

这里顺带说一句,Wireshark 打开 pcap 文件时如果提示"跟踪文件似乎已被截断",不要慌,多数时候是文件格式兼容问题,或者文件本身没下载完整。重新解压一遍 wireshark-traces-9e.zip,再次打开就可以了。实在不行就看文件大小,跟官方给的大小对比一下,经常是下载中断导致的。

3. TCP 实验核心环节拆解与实操

3.1 用 tcp-wireshark-trace-1.pcap 看三次握手

打开 pcap 后,先不要动过滤框,看看前几个报文。在 tcp-wireshark-trace-1.pcap 这种典型文件里,第一条 TCP 连接的开头必然是你最熟悉的三次握手:先是客户端发一个 SYN,服务端回一个 SYN-ACK,客户端再回一个 ACK。你可以在 Wireshark 的 Info 列直接看到[SYN][SYN, ACK][ACK]这样的标注。

这里有一个细节很多人会看漏:第一次握手 SYN 报文里,除了序列号(Sequence Number),还有一个叫“SEQ=0”的显示。这不是真实序列号,而是 Wireshark 为了方便阅读做的相对序列号显示。真实序列号是在 TCP 头的 Sequence Number 字段,一般是一个特别大的随机数。你可以右键单击列,选择"Protocol Preferences"里的相关选项,或者直接用查看菜单里的相对序列号开关关掉它,就能看到真实值。做实验时可以用相对值,因为好算;做实际排障时建议看真实值,因为要跟对端主机数据对比。

三次握手的核心目的不是“打个招呼”,而是同步初始序列号。SYN 消耗一个序列号,SYN-ACK 也消耗一个序列号,所以即便不带数据,这两个报文也会使序号加一。第三个 ACK 不消耗序列号,所以三次握手完成后,客户端那边下一次发送数据的序列号刚好是初始序列号加 1,服务端同理。这个细节在计算序号的题目里经常考,在 Wireshark 里也能直接验证。

3.2 序列号与确认号如何计算

序列号和确认号是 TCP 可靠传输的记账体系,也是实验报告里最容易丢分的计算题。在 Wireshark 里能看到每个报文的序列号(Seq)和确认号(Ack)。计算的原则其实就一句话:确认号 = 对端下一个期望收到的字节序号;序列号 = 本端本次发送数据的第一个字节序号。

我举个例子,假设客户端发了一个报文,Seq=1,Len=1448,MSS(最大分段大小)是 1448 字节。那这个报文实际携带的是第 1 到第 1448 个字节。服务端收到后,它期望收到的下一个字节序号是 1449,所以它回复的 ACK 报文里 Ack 字段就会是 1449。这个 1449 同时也是一个“已经正确收到前面所有数据”的信号。用 Wireshark 点开任意一个数据包,展开 TCP 头部,你能看到 Wireshark 已经帮你标好了 Len 字段、Seq 和 Ack,计算时只需要把上一个报文 Seq 加上 Len,看是否等于下一个 ACK 的 Ack 值。

但注意,不是所有报文都会触发立刻 ACK。TCP 有一个延迟确认机制,有时你连续发了好几个数据段,对方可能只回一个 ACK,这个 ACK 的确认号会是最后一个收到的字节序号加 1。你在 pcap 里看到“多个 Seq 对应一个 Ack”,不用觉得奇怪,这是 TCP 的累积确认机制,它表明接收方拿到的是连续的数据,中间没有空洞。

我自己的习惯是,在 Wireshark 里加一列tcp.len,专门看每个 TCP 负载的字节长度。因为 TCP 的 Len 和 IP 层的 Total Length 不一样,只有加上这列,才能快速做 Seq 和 Ack 的推算。默认情况下 Wireshark 不显示这个字段,你可以右键列名→Column Preferences→添加,输入tcp.len就能加上去。

3.3 用 Time-Sequence graph 看吞吐与重传

Wireshark 有一个特别强大的功能:Statistic → TCP Stream Graphs → Time-Sequence (Stevens)。这个图横轴是时间,纵轴是序列号,能画出 TCP 传输过程的字节级别变化。在分析 tcp-wireshark-trace-1.pcap 时,我强烈建议一定要打开这个图看一次。你会在图里看到一条不断上升的曲线,它代表的含义是:序列号随时间推进,数据在不断向前发送。

为什么这个图重要?因为如果 TCP 一切正常,曲线应该平滑上升,斜率代表发送速率。如果出现水平线段,说明序列号没有前进,这时候就是发生了重传:同样一个序列号的数据被重新发了一次,所以图像上呈现平台或倒退。如果曲线出现突然的台阶下降,那可能是乱序导致显示错位,或者报文重复。对于做实验而言,你能在图上看到明显的平台,然后接着继续上升,这往往就是慢启动或者重传的痕迹。作业里常问的“是否有重传、有多少个重传”,用这个图一眼就能看个大概。

具体操作是:先过滤出一条 TCP 流(tcp.stream eq 0),然后进到 Statistics → TCP Stream Graphs → Time-Sequence。图里能看到几条线:发送方序列号曲线、接收方 ACK 曲线。如果你把鼠标悬停在图上某一点,Wireshark 会在下方列表里自动定位到对应报文,这个交互非常方便。做实验汇报或者写报告时,可以直接截图,并在图上标出哪个位置是重传、哪个位置是窗口变化。

还有一个小经验:实际某个 trace 文件里可能不止一条 TCP 流,画 Time-Sequence 图时一定要先指定流序号。否则 Wireshark 默认画第一条流,和你心里想的可能是完全不同的连接。我在辅导同学实验时经常遇到“为什么我的图和书上不一样”的原因,多半就是没选对流。

3.4 拥塞控制窗口变化观察

说到拥塞控制,很多人觉得抽象。其实 Wireshark 里有一个更直观的功能:Statistics → TCP Stream Graphs → Window Scaling。这个图能看到接收窗口(rwnd)和拥塞窗口(cwnd)的变化。教材对拥塞控制的掌握要求通常是理解慢启动、拥塞避免、快速重传和快速恢复这几个状态,光靠背状态图特别容易绕晕,如果结合报文看,会清楚很多。

在 tcp-wireshark-trace-1.pcap 的实验里,虽然 trace 文件不一定完整包含拥塞窗口的逐包变化过程,但你仍然可以观察到一些关键信号。比如看 TCP 头的 Window 字段,这个字段代表接收方当前还能接收多少数据,也就是接收窗口的大小。如果这个值逐渐变小,说明接收方处理不过来,这会影响发送方的发送速率。Wireshark 里可以添加tcp.window_size_value列,直接观察窗口值的变化趋势。

至于拥塞窗口,默认 Wireshark 不直接显示 cwnd,需要借助图表或者额外扩展去计算。对初学者,我建议先不只是关心 cwnd 具体长度,而是观察发送模式的节奏:如果一个连接刚建立,前半段报文间隔紧密、窗口逐步翻倍增长,这大概率是慢启动阶段;当速率增长到一定阈值后增长放缓,说明进入拥塞避免。你可以通过 I/O Graph 看吞吐量的变化趋势,把时间跨度拉大,就能看到一个“加速→平稳→可能掉下去再爬”的曲线,这个曲线背后就是拥塞控制机制在工作。

说个容易混淆的:接收窗口和拥塞窗口是两个概念,一个由接收方决定,一个由网络状况决定,真正决定发送数据量的有效窗口是两者的最小值。实验里经常出现 Window 字段很大、但发送速率依然不高的情况,那就不是因为接收方慢,而是因为拥塞窗口限制住了发送量。看懂这一层,你对传输层的理解就超过大部分只背概念的同学了。

4. 常见问题与排查技巧实录

4.1 不联网时如何完成实验

我在实际辅导中,几乎每年都会遇到有人问:老师给的 tcp-wireshark-trace-1.pcap 打不开,或者打开后看不到数据。排查了几次发现,很多人是因为按实验手册去点击“抓包”按钮,结果电脑没联网,抓了个空文件,然后误以为文件坏了。这里再强调一遍:这个实验可以用现成 trace 文件完成,不需要联网抓包。

你只需要把 wireshark-traces-9e.zip 解压,在 Wireshark 里直接 File → Open,选择 tcp-wireshark-trace-1.pcap,就会看到完整的 TCP 报文。这个过程和分析你现场抓到的包没有任何区别,因为 pcap 文件本身就是把抓包结果保存下来的二进制格式。所以哪怕你在一个没有网络的机房、在图书馆角落、或在地铁上,都能把实验做完。这个特点对很多同学来说才是真正的友好之处。

当然,如果你确实想抓自己的包,我提醒一点:抓包之前把系统防火墙弹窗处理好,否则 Npcap 会静默失败。Windows 下建议用管理员身份运行 Wireshark,否则可能看不到网卡列表。macOS 上如果装的是 Wireshark,也要去“系统设置→隐私与安全性→网络”里允许抓包工具访问网络。

4.2 过滤不出来报文怎么办

打开 tcp-wireshark-trace-1.pcap 后,假设你输入了tcp,结果是一条报文都没有,这个情况我见过不少次。通常原因不是文件坏了,而是你输入的过滤表达式有问题。比如输入了全角字符的冒号、括号,或者把tcp.flags.syn == 1写成了tcp.flags.syn = 1(少写一个等号)。Wireshark 显示过滤语法里,比较操作是==,不是=,这个错误极其隐蔽,因为它不会报错,只是过滤框变红色。

另外,如果你输入tcp.flags.syn==1确实有结果,但只有几条,双击一条 SYN 报文后看不到 TCP 头,这也别慌,可能是你打开的是一个以太网帧里包含 IP but not TCP?这个现象通常说明你打开的 trace 文件不是 TCP 实验的 trace,而是别的实验的,比如 UDP 或者 ICMP。这时候核对一下文件名,确保打开的是 tcp-wireshark-trace-1.pcap,别把 tcp-wireshark-trace-2.pcap 或者其他实验文件混淆了。

还有个提升效率的小技巧:过滤出来三次握手的三个报文之后,右键其中一个报文,选择 Conversation Filter → TCP,Wireshark 会自动把过滤条件设置为tcp.stream eq N,你就能快速把这一整条 TCP 流的所有报文挑出来了。这个操作在写实验报告时特别好用,能保证你看的报文属于同一条连接,不会把不同连接的报文混在一起分析。

4.3 同一台机器的端口、连接和流

实验报告里通常有这么一个问题:客户端和服务器的 IP 地址、端口号分别是什么?很多人直接用 Wireshark 第一列 Source 和 Destination 去抄。你需要明白,IP 地址代表主机,端口号代表主机上的进程。比如你的电脑源 IP 是 192.168.1.105,源端口是 53240,访问的目标 IP 如果是 143.89.14.82,目标端口是 80,那么这就是一次普通的 HTTP 请求:你的浏览器在 53240 端口等待回包,服务器在 80 端口接收请求。

如果你把所有包含 53240 这个源端口的报文全选出来,会发现它们都属于同一条 TCP 连接,Wireshark 用 stream index 来标识。不同流之间的区分是四个要素:源 IP、源端口、目的 IP、目的端口。只要这四个值完全一致的一组报文,才算是一条连接。这一点在实际通信中极为重要,因为一台电脑可以同时打开几十个网页、跑着后台更新、连着远程桌面,全靠不同的源端口把这些进程分开。

做实验时,你可以点击 Statistics → Conversations,看到所有 TCP 流的四元组、收发字节数和起始时间。通过这个列表直接筛选最长的流、看传输量最大的连接,快速定位你想分析的对象。这份安排特别适合用在实验报告“分析流量特征”部分,比对着报文列表一个个翻效率高太多了。

4.4 从实验走向排查的扩展思路

很多人以为这本书的实验只是应付作业,考完就丢。其实不是,明白了这些基础操作后,你完全可以把技巧迁移到真实网络排查中。举几个最简单的例子:第一,看到网页打不开,你先抓包,过滤tcp.flags.syn == 1,如果只有 SYN 没有 SYN-ACK,说明对端根本没响应,大概率是服务没起来或中间设备挡了;如果 SYN-ACK 有但 ACK 没有,可能是客户端回程被丢包或者本机防火墙拦截。第二,视频会议卡顿,你就可以看 UDP 和 TCP 的用量分布,如果大量 UDP 包发生抖动,那就是实时媒体流的质量问题,优先检查网络延迟和丢包,而不是去看 TCP 重传。第三,文件传输慢,看 Time-Sequence 图,如果出现大量重传平台,就说明链路上有丢包,不是带宽不够。

这些排查方法和教材实验看起来是两件事,但底层逻辑完全一样:先确定连接能不能建立,再确认数据回包是否正常,最后看传输过程中有没有异常。自顶向下学习的好处就在于此,你从应用出发搞清楚了一个正常流程,那遇到不正常情况时,自然知道该在哪一层找原因。以后你再看 pcap 文件,就不会再心里发慌了,你已经有了一套清晰的检查路径。

文章写到这里,刚好把自顶向下第二部分的传输层核心和 TCP 实验串完。最后分享一个我自己的习惯:每次拿到一个新的 trace 文件,都不要急着看包,先在脑子里问自己三个问题——这条连接是怎么建立的,数据是怎么传的,连接是怎么结束的。然后带着这三个问题用 Wireshark 去验证。这个过程做多了,你会发现自己不需要刻意背 TCP 状态图,也能很自然地说出一个连接现在处于哪个阶段。网络的魅力就在这里,哪怕你只是打开一个 pcap,盯着那几十个报文看一会儿,也会觉得自己好像真的能看到数据在网络里流动。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询