1. 抓包之前先想清楚:TCP实验到底在验证什么很多人做Wireshark的TCP实验,打开软件就开始抓,抓完一看满屏的包,完全不知道从哪下手。我刚开始接触的时候也是这样,抓了上百个包,最后只看出"哦,有三次握手",然后就没了。后来带过几批新人做实验,我发现问题的根源不在工具,而在于动手之前没有想清楚:这个实验到底要验证哪些TCP的核心机制。TCP协议本身是一个庞大的话题,但落到Wireshark实验这个场景里,核心就是几件事:连接怎么建立、数据怎么传、连接怎么断、出了问题怎么恢复。这四件事对应到协议层面就是三次握手、数据传输与确认、四次挥手、超时重传与流量控制。你抓包的目的,就是用真实的报文把这几件事"看见"。所以这篇内容适合两类人:一类是正在做计算机网络课程实验的学生,需要一份能直接照着操作的指南;另一类是想重新梳理TCP底层细节的开发者,平时写代码调网络问题,总觉得抓包看到的东西和课本对不上。不管你是哪一类,我都会从环境准备开始,一步步把每个环节的操作、参数、判断依据讲清楚,并且告诉你哪些地方容易踩坑。关键词方面,Wireshark抓包、TCP三次握手、TCP四次挥手、序列号与确认号、超时重传、滑动窗口、流量控制这些会贯穿全文。我不会堆砌术语,而是把每个术语放到具体的报文里,让你看到它长什么样、为什么是这个值。另外说一句,做这个实验不需要多复杂的网络环境。一台电脑,装好Wireshark,能上网或者能访问局域网内的某台服务器就够了。真正重要的是你对报文字段的解读能力,这个能力一旦建立起来,以后排查任何网络问题都用得上。2. 实验环境搭建与抓包前的关键设置2.1 工具准备与网卡选择Wireshark的安装没什么好说的,官网下载对应系统的版本,一路下一步就行。Windows上安装的时候会提示安装Npcap,这个必须装,它是底层抓包驱动,不装的话Wireshark找不到任何网卡。安装过程中有一个选项叫"Restrict Npcap to administrators only",如果你不是管理员账户,建议不要勾选,否则普通用户权限下抓不了包。装完之后打开Wireshark,你会看到网卡列表。这里有个选择的问题:到底抓哪块网卡。如果你用的是有线网络,选以太网那块;如果用WiFi,选WLAN那块。怎么确认?看网卡旁边的实时流量波形图,哪个在动就选哪个。我见过有同学对着一个完全没流量的虚拟网卡抓了半天,还纳闷为什么一个包都没有。提示:如果你不确定选哪块网卡,可以先随便选一块,然后看Wireshark左上角的接口列表,有流量波动的就是当前活跃的网卡。选好网卡之后,先不要急着点开始。Wireshark默认会抓取网卡上的所有流量,在实验室或者宿舍这种共享网络环境下,你会抓到大量和你无关的包。所以下一步是设置过滤器。2.2 捕获过滤器的正确写法过滤器分两种:捕获过滤器(Capture Filter)和显示过滤器(Display Filter)。这两个的区别很关键,很多人搞混。捕获过滤器是在抓包之前设置的,它决定Wireshark"只抓哪些包",不满足条件的包直接丢弃,不写入内存。显示过滤器是在抓包之后用的,它不丢弃任何包,只是把满足条件的包"筛出来给你看"。捕获过滤器用BPF语法,显示过滤器用Wireshark自己的语法,两者写法完全不同。做TCP实验,我建议在捕获阶段就加上过滤条件,减少干扰。常用的捕获过滤器写法:# 只抓某台特定主机的流量 host 192.168.1.100 # 只抓某台主机且协议为TCP的流量 host 192.168.1.100 and tcp # 只抓某个端口相关的TCP流量 tcp port 80 # 抓某台主机与另一台主机之间的TCP流量 host 192.168.1.100 and host 203.0.113.5 and tcp这里有个实操经验:如果你要访问的是某个网站,先用ping或者nslookup拿到它的IP地址,然后把IP填进捕获过滤器。但要注意,很多大型网站用的是CDN,你解析出来的IP和实际建立TCP连接的IP可能不一样。更稳妥的做法是先用一个宽松的过滤器抓一小段,看看实际通信的对端IP是什么,再收紧过滤条件。注意:捕获过滤器一旦设置,不满足条件的包就彻底看不到了。如果你不确定过滤条件写得对不对,宁可先不加过滤器,抓完再用显示过滤器筛。抓多了可以删,抓少了就得重来。2.3 抓包位置的选择与影响这一点很多人忽略,但它直接影响你看到的报文内容。Wireshark抓包的位置决定了你能看到什么层次的协议数据。如果你在本机抓包,看到的是本机网卡进出的流量。这种情况下,你看到的TCP报文是完整的,序列号、确认号、窗口大小、标志位都能看到。但有一个问题:本机的TCP/IP协议栈可能会对报文做一些处理,比如网卡硬件卸载(TSO、LRO),导致你看到的报文长度和实际传输的不一致。如果你在中间设备上抓包(比如交换机镜像端口、路由器),看到的是经过转发的流量。这种方式的优点是不影响本机协议栈,看到的是"真实在网络上跑的包"。缺点是需要额外的设备配置权限。对于课程实验来说,本机抓包完全够用。但你要知道一个现象:有时候你会看到一些"奇怪"的报文,比如长度特别大的TCP段,或者校验和显示不正确。这通常是网卡硬件卸载导致的,不是真的有问题。可以在Wireshark的设置里关掉相关选项,或者直接忽略这些异常。2.4 实验目标的确定与流量构造抓包之前,你得明确这次要抓什么。TCP实验通常要覆盖以下几个场景:三次握手:建立连接的过程数据传输:发送数据、确认收到、窗口更新四次挥手:断开连接的过程超时重传:丢包后的恢复机制流量控制:接收方通过窗口大小控制发送方速率要触发这些场景,你需要构造相应的流量。最简单的办法是访问一个网页,HTTP over TCP的交互过程天然包含握手、数据传输和挥手。但网页访问的流量比较杂,有多个并发连接,分析起来不够干净。我更推荐用curl或者wget访问一个简单的HTTP资源,比如一个纯文本文件。这样只有一条TCP连接,报文序列清晰。如果要触发超时重传,可以用tc命令(Linux)或者网络模拟工具人为制造丢包。如果要观察流量控制,可以传输一个大文件,同时观察接收窗口的变化。# 用curl访问一个HTTP资源,只请求一次 curl -v http://example.com/test.txt # 如果要持续传输大文件观察窗口变化 curl -o /dev/null http://example.com/largefile.bin在Windows上,可以用PowerShell的Invoke-WebRequest,或者直接用浏览器访问。关键是一次只做一件事,不要同时开多个应用,否则抓到的包会混在一起,分析难度直线上升。3. 三次握手:从报文里读出连接建立的每一步3.1 抓取三次握手的操作步骤先启动Wireshark,选好网卡,设置捕获过滤器为tcp port 80(假设你访问的是HTTP服务)。然后点开始抓包,接着在浏览器或命令行里发起请求。请求完成后,回到Wireshark点停止。这时候你应该能看到一串TCP报文。找到第一个SYN包,这就是三次握手的起点。Wireshark的显示过滤器在这里很好用,输入tcp.flags.syn == 1就能筛出所有SYN包。三次握手的三个报文分别是:客户端发送SYN,序列号为初始序列号(ISN),比如Seq=0服务端回复SYN+ACK,序列号为服务端的ISN,确认号为客户端ISN+1客户端发送ACK,确认号为服务端ISN+1在Wireshark的报文详情面板里,展开"Transmission Control Protocol"这一层,你能看到所有关键字段。我建议你把这三个包的这几个字段都记下来:报文标志位序列号确认号窗口大小第一个包SYN客户端ISN0客户端窗口第二个包SYN, ACK服务端ISN客户端ISN+1服务端窗口第三个包ACK客户端ISN+1服务端ISN+1客户端窗口3.2 序列号与确认号的解读逻辑序列号和确认号是TCP里最容易让人迷糊的东西,但理解了之后其实很直观。序列号表示"我这个报文里携带的数据的第一个字节在整个数据流中的位置"。注意,SYN和FIN这两个标志位虽然不携带数据,但它们各占一个序列号。这就是为什么第二个包的确认号是"客户端ISN+1"——那个+1就是确认收到了客户端的SYN。确认号表示"我期望下一次收到你的数据的第一个字节的序号"。它等于"我已经收到的最后一个字节的序号+1"。这是一种累积确认机制,确认号N表示N之前的所有字节都收到了。举个例子:客户端ISN是1000,发送SYN。服务端回复SYN+ACK,确认号是1001,意思是"我收到了你的SYN(占序号1000),我期望你下一个字节从1001开始"。服务端的ISN假设是5000,那么客户端回复的ACK确认号就是5001。提示:Wireshark默认显示的是相对序列号,也就是把ISN显示为0,后续的序列号都是相对于ISN的偏移。这样看起来更直观。如果你想看真实的绝对序列号,可以在TCP协议首选项里关掉"Relative sequence numbers"。3.3 为什么是三次而不是两次或四次这个问题面试经常问,但很多人背答案不理解。从报文的角度看,三次握手的本质是双方各自确认自己和对方的收发能力都正常。第一次握手:客户端发SYN,服务端收到。服务端确认了"客户端的发送能力正常,我的接收能力正常"。 第二次握手:服务端发SYN+ACK,客户端收到。客户端确认了"我的发送能力正常,服务端的接收和发送能力都正常"。 第三次握手:客户端发ACK,服务端收到。服务端确认了"客户端的接收能力正常"。两次不够,因为服务端无法确认客户端能收到自己的报文。四次多余,因为第二次握手已经把服务端的SYN和ACK合并了。从抓包的角度,你可以验证这一点:第一个SYN包之后,如果服务端没有回复SYN+ACK,客户端会重传SYN。重传的时间间隔是指数退避的,通常是1秒、2秒、4秒、8秒这样递增。你可以在Wireshark里看到这些重传的SYN包,序列号相同,时间间隔逐渐拉大。3.4 握手阶段的常见异常与排查实际抓包时,三次握手不一定都顺利。几种常见情况:SYN没有响应:客户端发了SYN,但一直没有收到SYN+ACK。可能原因是对端服务没启动、防火墙拦截、或者路由不可达。在Wireshark里表现为只有SYN包,没有后续。SYN被拒绝:服务端回复的是RST+ACK而不是SYN+ACK。这通常意味着目标端口没有服务在监听。RST包在Wireshark里会标红,很容易识别。SYN重传:客户端发了多个SYN,序列号相同,时间间隔递增。这说明第一个SYN丢了或者响应丢了。如果最终握手成功,说明是偶发丢包;如果一直重传到超时,说明连接建立失败。SYN+ACK重传:服务端发了多个SYN+ACK,说明客户端没有回复ACK。可能是客户端的ACK丢了,也可能是客户端已经放弃了连接。排查的时候,重点看时间间隔和序列号。时间间隔能告诉你重传了几次、退避到什么程度;序列号能告诉你这些包是不是同一个连接的。4. 数据传输与确认:看懂滑动窗口和确认机制4.1 数据报文的抓取与筛选三次握手完成后,紧接着就是数据传输。在Wireshark里,你可以用显示过滤器tcp.len > 0来筛出所有携带数据的TCP报文。这些报文的TCP载荷长度大于0,说明它们承载了应用层数据。如果你访问的是一个网页,数据报文可能比较多,因为HTML、CSS、JS、图片都是通过TCP传输的。为了分析方便,建议访问一个纯文本文件,这样数据报文少而清晰。抓取数据报文的时候,注意观察几个关键字段:Seq:这个报文携带的数据的起始序号Ack:对之前收到的数据的确认Len:TCP载荷长度Win:接收窗口大小这四个字段的组合,能让你还原出整个数据传输的过程。4.2 序列号推进与累积确认TCP的数据传输是字节流,不是报文流。每个字节都有一个序号,序列号标识的是"这个报文里第一个字节的序号"。如果报文携带了100字节的数据,那么下一个报文的序列号就是当前序列号+100。确认号是累积的。假设客户端连续发了三个报文,序列号分别是1、101、201,每个携带100字节。服务端收到后,可以只发一个ACK,确认号是301,表示"1到300字节我都收到了,我期望下一个字节从301开始"。这就是累积确认,它减少了确认报文的数量。在Wireshark里,你可以通过tcp.analysis.ack_rtt字段看到每个ACK的往返时间。这个值反映了从发送数据到收到确认的时间差,是评估网络延迟的重要指标。注意:Wireshark的"Expert Information"功能会自动标记一些异常,比如重传、乱序、重复ACK。在菜单栏的"分析"里可以打开。做实验的时候,这个功能能帮你快速定位问题报文。4.3 滑动窗口的工作机制滑动窗口是TCP流量控制的核心。接收方通过TCP头部的窗口大小字段告诉发送方:"我还能接收多少字节的数据"。发送方根据这个值调整发送速率,确保不会把接收方的缓冲区撑爆。窗口大小是动态变化的。当接收方处理了缓冲区里的数据,窗口会变大;当接收方来不及处理,窗口会变小,甚至变成0。窗口为0的时候,发送方会停止发送数据,直到接收方发送窗口更新通知。在Wireshark里,你可以通过tcp.window_size_value字段看到每个报文的窗口大小。如果要做流量控制实验,可以传输一个大文件,同时观察窗口大小的变化曲线。Wireshark的"统计"菜单里有"TCP流图形",可以画出窗口大小随时间的变化。这里有一个容易混淆的概念:窗口缩放因子。TCP头部的窗口字段只有16位,最大表示65535字节。但在高速网络中,这个值太小了。所以TCP引入了窗口缩放选项,在握手阶段协商一个缩放因子,实际的窗口大小等于窗口字段值左移缩放因子位。Wireshark会自动计算实际窗口大小,显示在tcp.window_size字段里。4.4 延迟确认与Nagle算法的影响实际抓包时,你会发现有些数据报文没有立即被确认,而是等了一小段时间。这是延迟确认机制在起作用。接收方不会每收到一个报文就发一个ACK,而是等一小段时间(通常40ms到200ms),看有没有更多数据可以一起确认。这样可以减少ACK报文的数量,提高网络效率。另一个影响报文发送节奏的是Nagle算法。它要求发送方在收到前一个报文的ACK之前,不发送新的小报文。这样可以把多个小数据合并成一个大的TCP段发送,减少网络上的小包数量。这两个机制在Wireshark里的表现是:你可能会看到"一个ACK确认了多个数据报文",或者"多个小数据被合并成一个大的TCP段"。这些都不是异常,而是TCP的正常优化行为。但有时候这些优化会带来问题。比如在交互式应用中,延迟确认和Nagle算法叠加,可能导致明显的延迟。这时候可以通过设置TCP_NODELAY选项来禁用Nagle算法。在Wireshark里,你可以通过观察报文的时间间隔来判断是否存在这种问题。4.5 数据阶段的异常分析数据传输阶段常见的异常包括:重传:同一个序列号的数据被发送了多次。Wireshark会标记为"TCP Retransmission"。重传的原因可能是数据丢了,也可能是ACK丢了。快速重传:接收方收到乱序报文时,会立即发送重复ACK。发送方收到三个重复ACK后,不等超时就重传丢失的报文。这就是快速重传机制。在Wireshark里,你会看到三个相同的ACK,紧接着一个重传的数据报文。乱序:报文的序列号不连续,后面的报文先到了。Wireshark会标记为"TCP Out-of-Order"。乱序本身不是错误,但如果频繁发生,说明网络路径上存在多路径或者负载均衡。零窗口:接收方通告窗口大小为0,发送方停止发送。这通常意味着接收方应用层处理速度跟不上。如果零窗口持续很长时间,可能是接收方应用出了问题。窗口探测:当窗口为0时,发送方会定期发送窗口探测报文,询问接收方窗口是否更新。这个报文只携带1字节数据或者不携带数据,序列号是上一个已发送字节的序号。5. 四次挥手:连接释放的完整过程5.1 挥手报文的抓取与识别四次挥手发生在数据传输结束之后。主动关闭方发送FIN,被动关闭方回复ACK,然后被动关闭方也发送FIN,主动关闭方回复ACK。这四个报文完成了连接的完全释放。在Wireshark里,用显示过滤器tcp.flags.fin == 1可以筛出所有FIN包。通常你会看到两个FIN包,一个来自客户端,一个来自服务端。挥手的四个报文:主动关闭方发送FIN+ACK,序列号为最后一个数据字节的序号+1被动关闭方回复ACK,确认号为FIN的序列号+1被动关闭方发送FIN+ACK,序列号为它最后一个数据字节的序号+1主动关闭方回复ACK,确认号为FIN的序列号+1注意,FIN和SYN一样,虽然不携带数据,但各占一个序列号。这就是为什么确认号要+1。5.2 为什么挥手需要四次挥手比握手多一次,原因是TCP连接是全双工的。握手的时候,服务端可以把SYN和ACK合并成一个报文,因为服务端收到SYN后可以立即决定是否接受连接。但挥手的时候,被动关闭方收到FIN后,可能还有数据没发完,不能立即发送FIN。所以它先回复一个ACK,等数据发完了再发送FIN。这就导致了四次挥手:FIN、ACK、FIN、ACK。中间的两个报文不能合并,因为被动关闭方的数据发送和连接关闭是两个独立的事件。在某些情况下,被动关闭方没有数据要发了,它可以把ACK和FIN合并成一个报文,这样就变成了三次挥手。在Wireshark里,你会看到第二个报文同时带有ACK和FIN标志。5.3 TIME_WAIT状态的意义主动关闭方发送最后一个ACK后,会进入TIME_WAIT状态,等待2MSL(最大报文段生存时间)后才真正关闭连接。在Linux上,这个时间通常是60秒。TIME_WAIT的作用有两个:一是确保最后一个ACK能到达被动关闭方,如果ACK丢了,被动关闭方会重传FIN,主动关闭方还能响应;二是让本次连接的所有报文在网络中消失,避免影响后续使用相同四元组的新连接。在Wireshark里,你无法直接看到TIME_WAIT状态,因为它是协议栈内部的状态。但你可以通过netstat命令查看:# Linux/Mac netstat -an | grep TIME_WAIT # Windows netstat -an | findstr TIME_WAIT如果TIME_WAIT状态的连接过多,可能会耗尽本地端口资源。这时候可以调整内核参数,比如开启TIME_WAIT重用。但这是把双刃剑,需要根据实际场景权衡。5.4 挥手阶段的异常情况FIN重传:主动关闭方发了FIN,但没有收到ACK,会重传FIN。在Wireshark里表现为多个FIN包,序列号相同。RST代替FIN:有时候连接不是正常关闭的,而是被RST强制终止。RST包表示"连接异常,立即终止"。常见于应用崩溃、端口关闭、或者协议错误。在Wireshark里,RST包会被标红。半关闭状态:一方发送了FIN,但另一方还在发送数据。这时候连接处于半关闭状态。在Wireshark里,你会看到FIN之后还有数据报文。这是正常的,TCP允许半关闭。连接被拒绝:如果主动关闭方发送FIN后收到RST,说明对端已经不认这个连接了。可能是对端已经关闭了连接,或者中间设备拦截了报文。6. 超时重传与流量控制:TCP的可靠性保障6.1 超时重传的触发条件与观察方法超时重传是TCP保证可靠性的核心机制。发送方每发送一个报文,就启动一个定时器。如果在定时器超时之前没有收到确认,就重传这个报文。在Wireshark里,超时重传的报文会被标记为"TCP Retransmission"。你可以通过tcp.analysis.retransmission过滤器筛出所有重传报文。要人为制造重传,可以用网络模拟工具制造丢包。在Linux上,tc命令可以模拟丢包:# 在网卡eth0上模拟10%的丢包率 sudo tc qdisc add dev eth0 root netem loss 10% # 实验结束后删除规则 sudo tc qdisc del dev eth0 root在Windows上,可以用Clumsy或者NetLimiter这类工具模拟丢包。观察重传的时候,注意重传的时间间隔。TCP使用指数退避算法,第一次重传等待1个RTO(重传超时时间),第二次等待2个RTO,第三次等待4个RTO,以此类推。RTO本身是根据RTT动态计算的,Wireshark会显示每个重传报文的相对时间。6.2 快速重传与重复ACK超时重传的问题是等待时间太长。如果发送方收到三个重复ACK,就可以推断某个报文丢了,立即重传,不用等超时。这就是快速重传。重复ACK的产生过程:接收方收到乱序报文时,会立即发送ACK,确认号还是期望的那个序号。发送方收到多个相同的ACK,就知道中间有报文丢了。在Wireshark里,你会看到这样的序列:发送方发了Seq=1、Seq=101、Seq=201三个报文,但Seq=101丢了。接收方收到Seq=1后回复Ack=101,收到Seq=201后还是回复Ack=101(因为101没收到)。发送方收到三个Ack=101后,立即重传Seq=101。Wireshark会把重复的ACK标记为"TCP Dup ACK",把快速重传的报文标记为"TCP Fast Retransmission"。6.3 流量控制与拥塞控制的区别这两个概念经常被混淆,但在Wireshark里它们的表现不同。流量控制是接收方通过窗口大小告诉发送方"我能收多少"。它是端到端的,只涉及收发双方。在Wireshark里,你看到的是窗口大小的变化。拥塞控制是发送方根据网络状况调整发送速率。它涉及整个网络路径。在Wireshark里,你看到的是发送速率的変化,以及拥塞窗口的变化(但拥塞窗口是发送方内部状态,Wireshark看不到,只能通过发送速率推断)。拥塞控制有四个阶段:慢启动、拥塞避免、快速重传、快速恢复。在Wireshark里,你可以通过"统计"菜单里的"TCP流图形"看到吞吐量的变化曲线。慢启动阶段吞吐量指数增长,拥塞避免阶段线性增长,发生丢包后吞吐量骤降。6.4 零窗口与窗口探测的实战分析当接收方的缓冲区满了,它会通告窗口大小为0。发送方收到零窗口通知后,停止发送数据,但会定期发送窗口探测报文。窗口探测报文的特点是:序列号是上一个已发送字节的序号,携带1字节数据或者不携带数据。接收方收到探测报文后,如果窗口已经更新,会回复新的窗口大小;如果窗口还是0,会回复一个ACK,窗口仍然为0。在Wireshark里,你可以用tcp.analysis.zero_window过滤器找到零窗口报文,用tcp.analysis.window_update找到窗口更新报文。零窗口持续的时间越长,说明接收方应用处理越慢。如果零窗口一直不更新,可能是接收方应用卡死了。这时候需要检查接收方的应用状态和系统资源。7. 常见问题与排查技巧实录7.1 抓不到包或抓到的包不完整这是新手最常遇到的问题。可能的原因和排查方法:现象可能原因排查方法一个包都没有选错网卡看接口列表的流量波形,选活跃的网卡只有部分包捕获过滤器太严先去掉过滤器,抓完再用显示过滤器筛包不完整网卡硬件卸载关闭TSO/LRO,或在Wireshark里忽略校验和错误看不到应用层数据加密协议HTTPS流量是加密的,只能看到TCP层,看不到HTTP内容提示:如果抓HTTPS流量,你只能分析TCP层的行为,看不到HTTP请求和响应。要做应用层分析,需要配置SSLKEYLOGFILE或者使用其他方法。7.2 序列号和确认号看不懂这是概念问题,不是操作问题。记住几个要点:序列号是字节序号,不是报文序号SYN和FIN各占一个序列号确认号是累积确认,表示期望收到的下一个字节Wireshark默认显示相对序列号,ISN显示为0如果还是看不懂,找一个简单的HTTP请求,把每个报文的Seq、Ack、Len三个字段列出来,手动算一遍。算过一遍就明白了。7.3 重传和乱序分不清重传和乱序在Wireshark里都会显示为"异常的序列号",但它们的含义不同:重传:同一个序列号的数据被发送了多次,说明数据可能丢了乱序:序列号不连续,后面的报文先到了,说明网络路径上存在多路径Wireshark会自动标记这两种情况,但有时候会误判。判断的依据是时间和上下文。如果同一个序列号在短时间内出现多次,大概率是重传;如果序列号跳跃但每个只出现一次,大概率是乱序。7.4 窗口大小为什么一直是0零窗口说明接收方缓冲区满了。排查思路:检查接收方应用是否在处理数据,还是卡住了检查接收方的系统资源,CPU、内存是否正常检查接收方的TCP接收缓冲区设置,是否太小如果是自己写的应用,检查读取数据的逻辑是否有问题在Linux上,可以用ss -tln查看socket的接收队列和发送队列。如果Recv-Q很大,说明应用没有及时读取数据。7.5 实验报告怎么写才不像抄的这个问题很实际。我的建议是:不要只贴截图,要写你的分析过程。比如三次握手,不要只放三个包的截图,要写出:你抓的是什么流量,为什么选这个三个包的序列号和确认号分别是多少,为什么是这个值你观察到了什么异常(如果有),你是怎么判断的你对三次握手有了什么新的理解这样的报告才有价值,也才能体现出你真的动手做了实验,而不是复制粘贴。8. 从实验到实战:这些技能能用在什么地方做完这个实验,你获得的不只是几个截图,而是一种用报文验证协议行为的能力。这种能力在实际工作中有很多应用场景。排查网络性能问题:用户反馈某个接口很慢,你可以抓包看看是TCP重传多、窗口小、还是RTT高。每个指标对应不同的优化方向。调试分布式系统:微服务之间的调用超时,抓包能看到是连接建立慢、数据传输慢、还是对端处理慢。比看日志更直接。理解安全攻击:SYN Flood、RST攻击、会话劫持,这些攻击在Wireshark里都有明显的报文特征。理解了正常行为,才能识别异常行为。优化应用性能:通过观察TCP的行为,你可以判断是否需要调整Nagle算法、延迟确认、窗口大小等参数。这些调整对高并发应用的影响很大。我个人在实际工作中的体会是,抓包分析这项技能,入门容易精通难。工具的使用几天就能学会,但报文背后的协议逻辑和网络行为,需要长期的积累和思考。每次遇到网络问题,不要急着搜答案,先抓个包看看,往往能发现意想不到的线索。最后分享一个小技巧:Wireshark的"追踪TCP流"功能(Follow TCP Stream)可以把一条TCP连接的所有应用层数据拼在一起显示。分析HTTP请求响应的时候特别有用,能直接看到完整的交互内容。但要注意,这个功能只对未加密的流量有效,HTTPS流量看到的是乱码。
1. 抓包之前先想清楚:TCP实验到底在验证什么很多人做Wireshark的TCP实验,打开软件就开始抓,抓完一看满屏的包,完全不知道从哪下手。我刚开始接触的时候也是这样,抓了上百个包,最后只看出"哦,有三次握手",然后就没了。后来带过几批新人做实验,我发现问题的根源不在工具,而在于动手之前没有想清楚:这个实验到底要验证哪些TCP的核心机制。TCP协议本身是一个庞大的话题,但落到Wireshark实验这个场景里,核心就是几件事:连接怎么建立、数据怎么传、连接怎么断、出了问题怎么恢复。这四件事对应到协议层面就是三次握手、数据传输与确认、四次挥手、超时重传与流量控制。你抓包的目的,就是用真实的报文把这几件事"看见"。所以这篇内容适合两类人:一类是正在做计算机网络课程实验的学生,需要一份能直接照着操作的指南;另一类是想重新梳理TCP底层细节的开发者,平时写代码调网络问题,总觉得抓包看到的东西和课本对不上。不管你是哪一类,我都会从环境准备开始,一步步把每个环节的操作、参数、判断依据讲清楚,并且告诉你哪些地方容易踩坑。关键词方面,Wireshark抓包、TCP三次握手、TCP四次挥手、序列号与确认号、超时重传、滑动窗口、流量控制这些会贯穿全文。我不会堆砌术语,而是把每个术语放到具体的报文里,让你看到它长什么样、为什么是这个值。另外说一句,做这个实验不需要多复杂的网络环境。一台电脑,装好Wireshark,能上网或者能访问局域网内的某台服务器就够了。真正重要的是你对报文字段的解读能力,这个能力一旦建立起来,以后排查任何网络问题都用得上。2. 实验环境搭建与抓包前的关键设置2.1 工具准备与网卡选择Wireshark的安装没什么好说的,官网下载对应系统的版本,一路下一步就行。Windows上安装的时候会提示安装Npcap,这个必须装,它是底层抓包驱动,不装的话Wireshark找不到任何网卡。安装过程中有一个选项叫"Restrict Npcap to administrators only",如果你不是管理员账户,建议不要勾选,否则普通用户权限下抓不了包。装完之后打开Wireshark,你会看到网卡列表。这里有个选择的问题:到底抓哪块网卡。如果你用的是有线网络,选以太网那块;如果用WiFi,选WLAN那块。怎么确认?看网卡旁边的实时流量波形图,哪个在动就选哪个。我见过有同学对着一个完全没流量的虚拟网卡抓了半天,还纳闷为什么一个包都没有。提示:如果你不确定选哪块网卡,可以先随便选一块,然后看Wireshark左上角的接口列表,有流量波动的就是当前活跃的网卡。选好网卡之后,先不要急着点开始。Wireshark默认会抓取网卡上的所有流量,在实验室或者宿舍这种共享网络环境下,你会抓到大量和你无关的包。所以下一步是设置过滤器。2.2 捕获过滤器的正确写法过滤器分两种:捕获过滤器(Capture Filter)和显示过滤器(Display Filter)。这两个的区别很关键,很多人搞混。捕获过滤器是在抓包之前设置的,它决定Wireshark"只抓哪些包",不满足条件的包直接丢弃,不写入内存。显示过滤器是在抓包之后用的,它不丢弃任何包,只是把满足条件的包"筛出来给你看"。捕获过滤器用BPF语法,显示过滤器用Wireshark自己的语法,两者写法完全不同。做TCP实验,我建议在捕获阶段就加上过滤条件,减少干扰。常用的捕获过滤器写法:# 只抓某台特定主机的流量 host 192.168.1.100 # 只抓某台主机且协议为TCP的流量 host 192.168.1.100 and tcp # 只抓某个端口相关的TCP流量 tcp port 80 # 抓某台主机与另一台主机之间的TCP流量 host 192.168.1.100 and host 203.0.113.5 and tcp这里有个实操经验:如果你要访问的是某个网站,先用ping或者nslookup拿到它的IP地址,然后把IP填进捕获过滤器。但要注意,很多大型网站用的是CDN,你解析出来的IP和实际建立TCP连接的IP可能不一样。更稳妥的做法是先用一个宽松的过滤器抓一小段,看看实际通信的对端IP是什么,再收紧过滤条件。注意:捕获过滤器一旦设置,不满足条件的包就彻底看不到了。如果你不确定过滤条件写得对不对,宁可先不加过滤器,抓完再用显示过滤器筛。抓多了可以删,抓少了就得重来。2.3 抓包位置的选择与影响这一点很多人忽略,但它直接影响你看到的报文内容。Wireshark抓包的位置决定了你能看到什么层次的协议数据。如果你在本机抓包,看到的是本机网卡进出的流量。这种情况下,你看到的TCP报文是完整的,序列号、确认号、窗口大小、标志位都能看到。但有一个问题:本机的TCP/IP协议栈可能会对报文做一些处理,比如网卡硬件卸载(TSO、LRO),导致你看到的报文长度和实际传输的不一致。如果你在中间设备上抓包(比如交换机镜像端口、路由器),看到的是经过转发的流量。这种方式的优点是不影响本机协议栈,看到的是"真实在网络上跑的包"。缺点是需要额外的设备配置权限。对于课程实验来说,本机抓包完全够用。但你要知道一个现象:有时候你会看到一些"奇怪"的报文,比如长度特别大的TCP段,或者校验和显示不正确。这通常是网卡硬件卸载导致的,不是真的有问题。可以在Wireshark的设置里关掉相关选项,或者直接忽略这些异常。2.4 实验目标的确定与流量构造抓包之前,你得明确这次要抓什么。TCP实验通常要覆盖以下几个场景:三次握手:建立连接的过程数据传输:发送数据、确认收到、窗口更新四次挥手:断开连接的过程超时重传:丢包后的恢复机制流量控制:接收方通过窗口大小控制发送方速率要触发这些场景,你需要构造相应的流量。最简单的办法是访问一个网页,HTTP over TCP的交互过程天然包含握手、数据传输和挥手。但网页访问的流量比较杂,有多个并发连接,分析起来不够干净。我更推荐用curl或者wget访问一个简单的HTTP资源,比如一个纯文本文件。这样只有一条TCP连接,报文序列清晰。如果要触发超时重传,可以用tc命令(Linux)或者网络模拟工具人为制造丢包。如果要观察流量控制,可以传输一个大文件,同时观察接收窗口的变化。# 用curl访问一个HTTP资源,只请求一次 curl -v http://example.com/test.txt # 如果要持续传输大文件观察窗口变化 curl -o /dev/null http://example.com/largefile.bin在Windows上,可以用PowerShell的Invoke-WebRequest,或者直接用浏览器访问。关键是一次只做一件事,不要同时开多个应用,否则抓到的包会混在一起,分析难度直线上升。3. 三次握手:从报文里读出连接建立的每一步3.1 抓取三次握手的操作步骤先启动Wireshark,选好网卡,设置捕获过滤器为tcp port 80(假设你访问的是HTTP服务)。然后点开始抓包,接着在浏览器或命令行里发起请求。请求完成后,回到Wireshark点停止。这时候你应该能看到一串TCP报文。找到第一个SYN包,这就是三次握手的起点。Wireshark的显示过滤器在这里很好用,输入tcp.flags.syn == 1就能筛出所有SYN包。三次握手的三个报文分别是:客户端发送SYN,序列号为初始序列号(ISN),比如Seq=0服务端回复SYN+ACK,序列号为服务端的ISN,确认号为客户端ISN+1客户端发送ACK,确认号为服务端ISN+1在Wireshark的报文详情面板里,展开"Transmission Control Protocol"这一层,你能看到所有关键字段。我建议你把这三个包的这几个字段都记下来:报文标志位序列号确认号窗口大小第一个包SYN客户端ISN0客户端窗口第二个包SYN, ACK服务端ISN客户端ISN+1服务端窗口第三个包ACK客户端ISN+1服务端ISN+1客户端窗口3.2 序列号与确认号的解读逻辑序列号和确认号是TCP里最容易让人迷糊的东西,但理解了之后其实很直观。序列号表示"我这个报文里携带的数据的第一个字节在整个数据流中的位置"。注意,SYN和FIN这两个标志位虽然不携带数据,但它们各占一个序列号。这就是为什么第二个包的确认号是"客户端ISN+1"——那个+1就是确认收到了客户端的SYN。确认号表示"我期望下一次收到你的数据的第一个字节的序号"。它等于"我已经收到的最后一个字节的序号+1"。这是一种累积确认机制,确认号N表示N之前的所有字节都收到了。举个例子:客户端ISN是1000,发送SYN。服务端回复SYN+ACK,确认号是1001,意思是"我收到了你的SYN(占序号1000),我期望你下一个字节从1001开始"。服务端的ISN假设是5000,那么客户端回复的ACK确认号就是5001。提示:Wireshark默认显示的是相对序列号,也就是把ISN显示为0,后续的序列号都是相对于ISN的偏移。这样看起来更直观。如果你想看真实的绝对序列号,可以在TCP协议首选项里关掉"Relative sequence numbers"。3.3 为什么是三次而不是两次或四次这个问题面试经常问,但很多人背答案不理解。从报文的角度看,三次握手的本质是双方各自确认自己和对方的收发能力都正常。第一次握手:客户端发SYN,服务端收到。服务端确认了"客户端的发送能力正常,我的接收能力正常"。 第二次握手:服务端发SYN+ACK,客户端收到。客户端确认了"我的发送能力正常,服务端的接收和发送能力都正常"。 第三次握手:客户端发ACK,服务端收到。服务端确认了"客户端的接收能力正常"。两次不够,因为服务端无法确认客户端能收到自己的报文。四次多余,因为第二次握手已经把服务端的SYN和ACK合并了。从抓包的角度,你可以验证这一点:第一个SYN包之后,如果服务端没有回复SYN+ACK,客户端会重传SYN。重传的时间间隔是指数退避的,通常是1秒、2秒、4秒、8秒这样递增。你可以在Wireshark里看到这些重传的SYN包,序列号相同,时间间隔逐渐拉大。3.4 握手阶段的常见异常与排查实际抓包时,三次握手不一定都顺利。几种常见情况:SYN没有响应:客户端发了SYN,但一直没有收到SYN+ACK。可能原因是对端服务没启动、防火墙拦截、或者路由不可达。在Wireshark里表现为只有SYN包,没有后续。SYN被拒绝:服务端回复的是RST+ACK而不是SYN+ACK。这通常意味着目标端口没有服务在监听。RST包在Wireshark里会标红,很容易识别。SYN重传:客户端发了多个SYN,序列号相同,时间间隔递增。这说明第一个SYN丢了或者响应丢了。如果最终握手成功,说明是偶发丢包;如果一直重传到超时,说明连接建立失败。SYN+ACK重传:服务端发了多个SYN+ACK,说明客户端没有回复ACK。可能是客户端的ACK丢了,也可能是客户端已经放弃了连接。排查的时候,重点看时间间隔和序列号。时间间隔能告诉你重传了几次、退避到什么程度;序列号能告诉你这些包是不是同一个连接的。4. 数据传输与确认:看懂滑动窗口和确认机制4.1 数据报文的抓取与筛选三次握手完成后,紧接着就是数据传输。在Wireshark里,你可以用显示过滤器tcp.len > 0来筛出所有携带数据的TCP报文。这些报文的TCP载荷长度大于0,说明它们承载了应用层数据。如果你访问的是一个网页,数据报文可能比较多,因为HTML、CSS、JS、图片都是通过TCP传输的。为了分析方便,建议访问一个纯文本文件,这样数据报文少而清晰。抓取数据报文的时候,注意观察几个关键字段:Seq:这个报文携带的数据的起始序号Ack:对之前收到的数据的确认Len:TCP载荷长度Win:接收窗口大小这四个字段的组合,能让你还原出整个数据传输的过程。4.2 序列号推进与累积确认TCP的数据传输是字节流,不是报文流。每个字节都有一个序号,序列号标识的是"这个报文里第一个字节的序号"。如果报文携带了100字节的数据,那么下一个报文的序列号就是当前序列号+100。确认号是累积的。假设客户端连续发了三个报文,序列号分别是1、101、201,每个携带100字节。服务端收到后,可以只发一个ACK,确认号是301,表示"1到300字节我都收到了,我期望下一个字节从301开始"。这就是累积确认,它减少了确认报文的数量。在Wireshark里,你可以通过tcp.analysis.ack_rtt字段看到每个ACK的往返时间。这个值反映了从发送数据到收到确认的时间差,是评估网络延迟的重要指标。注意:Wireshark的"Expert Information"功能会自动标记一些异常,比如重传、乱序、重复ACK。在菜单栏的"分析"里可以打开。做实验的时候,这个功能能帮你快速定位问题报文。4.3 滑动窗口的工作机制滑动窗口是TCP流量控制的核心。接收方通过TCP头部的窗口大小字段告诉发送方:"我还能接收多少字节的数据"。发送方根据这个值调整发送速率,确保不会把接收方的缓冲区撑爆。窗口大小是动态变化的。当接收方处理了缓冲区里的数据,窗口会变大;当接收方来不及处理,窗口会变小,甚至变成0。窗口为0的时候,发送方会停止发送数据,直到接收方发送窗口更新通知。在Wireshark里,你可以通过tcp.window_size_value字段看到每个报文的窗口大小。如果要做流量控制实验,可以传输一个大文件,同时观察窗口大小的变化曲线。Wireshark的"统计"菜单里有"TCP流图形",可以画出窗口大小随时间的变化。这里有一个容易混淆的概念:窗口缩放因子。TCP头部的窗口字段只有16位,最大表示65535字节。但在高速网络中,这个值太小了。所以TCP引入了窗口缩放选项,在握手阶段协商一个缩放因子,实际的窗口大小等于窗口字段值左移缩放因子位。Wireshark会自动计算实际窗口大小,显示在tcp.window_size字段里。4.4 延迟确认与Nagle算法的影响实际抓包时,你会发现有些数据报文没有立即被确认,而是等了一小段时间。这是延迟确认机制在起作用。接收方不会每收到一个报文就发一个ACK,而是等一小段时间(通常40ms到200ms),看有没有更多数据可以一起确认。这样可以减少ACK报文的数量,提高网络效率。另一个影响报文发送节奏的是Nagle算法。它要求发送方在收到前一个报文的ACK之前,不发送新的小报文。这样可以把多个小数据合并成一个大的TCP段发送,减少网络上的小包数量。这两个机制在Wireshark里的表现是:你可能会看到"一个ACK确认了多个数据报文",或者"多个小数据被合并成一个大的TCP段"。这些都不是异常,而是TCP的正常优化行为。但有时候这些优化会带来问题。比如在交互式应用中,延迟确认和Nagle算法叠加,可能导致明显的延迟。这时候可以通过设置TCP_NODELAY选项来禁用Nagle算法。在Wireshark里,你可以通过观察报文的时间间隔来判断是否存在这种问题。4.5 数据阶段的异常分析数据传输阶段常见的异常包括:重传:同一个序列号的数据被发送了多次。Wireshark会标记为"TCP Retransmission"。重传的原因可能是数据丢了,也可能是ACK丢了。快速重传:接收方收到乱序报文时,会立即发送重复ACK。发送方收到三个重复ACK后,不等超时就重传丢失的报文。这就是快速重传机制。在Wireshark里,你会看到三个相同的ACK,紧接着一个重传的数据报文。乱序:报文的序列号不连续,后面的报文先到了。Wireshark会标记为"TCP Out-of-Order"。乱序本身不是错误,但如果频繁发生,说明网络路径上存在多路径或者负载均衡。零窗口:接收方通告窗口大小为0,发送方停止发送。这通常意味着接收方应用层处理速度跟不上。如果零窗口持续很长时间,可能是接收方应用出了问题。窗口探测:当窗口为0时,发送方会定期发送窗口探测报文,询问接收方窗口是否更新。这个报文只携带1字节数据或者不携带数据,序列号是上一个已发送字节的序号。5. 四次挥手:连接释放的完整过程5.1 挥手报文的抓取与识别四次挥手发生在数据传输结束之后。主动关闭方发送FIN,被动关闭方回复ACK,然后被动关闭方也发送FIN,主动关闭方回复ACK。这四个报文完成了连接的完全释放。在Wireshark里,用显示过滤器tcp.flags.fin == 1可以筛出所有FIN包。通常你会看到两个FIN包,一个来自客户端,一个来自服务端。挥手的四个报文:主动关闭方发送FIN+ACK,序列号为最后一个数据字节的序号+1被动关闭方回复ACK,确认号为FIN的序列号+1被动关闭方发送FIN+ACK,序列号为它最后一个数据字节的序号+1主动关闭方回复ACK,确认号为FIN的序列号+1注意,FIN和SYN一样,虽然不携带数据,但各占一个序列号。这就是为什么确认号要+1。5.2 为什么挥手需要四次挥手比握手多一次,原因是TCP连接是全双工的。握手的时候,服务端可以把SYN和ACK合并成一个报文,因为服务端收到SYN后可以立即决定是否接受连接。但挥手的时候,被动关闭方收到FIN后,可能还有数据没发完,不能立即发送FIN。所以它先回复一个ACK,等数据发完了再发送FIN。这就导致了四次挥手:FIN、ACK、FIN、ACK。中间的两个报文不能合并,因为被动关闭方的数据发送和连接关闭是两个独立的事件。在某些情况下,被动关闭方没有数据要发了,它可以把ACK和FIN合并成一个报文,这样就变成了三次挥手。在Wireshark里,你会看到第二个报文同时带有ACK和FIN标志。5.3 TIME_WAIT状态的意义主动关闭方发送最后一个ACK后,会进入TIME_WAIT状态,等待2MSL(最大报文段生存时间)后才真正关闭连接。在Linux上,这个时间通常是60秒。TIME_WAIT的作用有两个:一是确保最后一个ACK能到达被动关闭方,如果ACK丢了,被动关闭方会重传FIN,主动关闭方还能响应;二是让本次连接的所有报文在网络中消失,避免影响后续使用相同四元组的新连接。在Wireshark里,你无法直接看到TIME_WAIT状态,因为它是协议栈内部的状态。但你可以通过netstat命令查看:# Linux/Mac netstat -an | grep TIME_WAIT # Windows netstat -an | findstr TIME_WAIT如果TIME_WAIT状态的连接过多,可能会耗尽本地端口资源。这时候可以调整内核参数,比如开启TIME_WAIT重用。但这是把双刃剑,需要根据实际场景权衡。5.4 挥手阶段的异常情况FIN重传:主动关闭方发了FIN,但没有收到ACK,会重传FIN。在Wireshark里表现为多个FIN包,序列号相同。RST代替FIN:有时候连接不是正常关闭的,而是被RST强制终止。RST包表示"连接异常,立即终止"。常见于应用崩溃、端口关闭、或者协议错误。在Wireshark里,RST包会被标红。半关闭状态:一方发送了FIN,但另一方还在发送数据。这时候连接处于半关闭状态。在Wireshark里,你会看到FIN之后还有数据报文。这是正常的,TCP允许半关闭。连接被拒绝:如果主动关闭方发送FIN后收到RST,说明对端已经不认这个连接了。可能是对端已经关闭了连接,或者中间设备拦截了报文。6. 超时重传与流量控制:TCP的可靠性保障6.1 超时重传的触发条件与观察方法超时重传是TCP保证可靠性的核心机制。发送方每发送一个报文,就启动一个定时器。如果在定时器超时之前没有收到确认,就重传这个报文。在Wireshark里,超时重传的报文会被标记为"TCP Retransmission"。你可以通过tcp.analysis.retransmission过滤器筛出所有重传报文。要人为制造重传,可以用网络模拟工具制造丢包。在Linux上,tc命令可以模拟丢包:# 在网卡eth0上模拟10%的丢包率 sudo tc qdisc add dev eth0 root netem loss 10% # 实验结束后删除规则 sudo tc qdisc del dev eth0 root在Windows上,可以用Clumsy或者NetLimiter这类工具模拟丢包。观察重传的时候,注意重传的时间间隔。TCP使用指数退避算法,第一次重传等待1个RTO(重传超时时间),第二次等待2个RTO,第三次等待4个RTO,以此类推。RTO本身是根据RTT动态计算的,Wireshark会显示每个重传报文的相对时间。6.2 快速重传与重复ACK超时重传的问题是等待时间太长。如果发送方收到三个重复ACK,就可以推断某个报文丢了,立即重传,不用等超时。这就是快速重传。重复ACK的产生过程:接收方收到乱序报文时,会立即发送ACK,确认号还是期望的那个序号。发送方收到多个相同的ACK,就知道中间有报文丢了。在Wireshark里,你会看到这样的序列:发送方发了Seq=1、Seq=101、Seq=201三个报文,但Seq=101丢了。接收方收到Seq=1后回复Ack=101,收到Seq=201后还是回复Ack=101(因为101没收到)。发送方收到三个Ack=101后,立即重传Seq=101。Wireshark会把重复的ACK标记为"TCP Dup ACK",把快速重传的报文标记为"TCP Fast Retransmission"。6.3 流量控制与拥塞控制的区别这两个概念经常被混淆,但在Wireshark里它们的表现不同。流量控制是接收方通过窗口大小告诉发送方"我能收多少"。它是端到端的,只涉及收发双方。在Wireshark里,你看到的是窗口大小的变化。拥塞控制是发送方根据网络状况调整发送速率。它涉及整个网络路径。在Wireshark里,你看到的是发送速率的変化,以及拥塞窗口的变化(但拥塞窗口是发送方内部状态,Wireshark看不到,只能通过发送速率推断)。拥塞控制有四个阶段:慢启动、拥塞避免、快速重传、快速恢复。在Wireshark里,你可以通过"统计"菜单里的"TCP流图形"看到吞吐量的变化曲线。慢启动阶段吞吐量指数增长,拥塞避免阶段线性增长,发生丢包后吞吐量骤降。6.4 零窗口与窗口探测的实战分析当接收方的缓冲区满了,它会通告窗口大小为0。发送方收到零窗口通知后,停止发送数据,但会定期发送窗口探测报文。窗口探测报文的特点是:序列号是上一个已发送字节的序号,携带1字节数据或者不携带数据。接收方收到探测报文后,如果窗口已经更新,会回复新的窗口大小;如果窗口还是0,会回复一个ACK,窗口仍然为0。在Wireshark里,你可以用tcp.analysis.zero_window过滤器找到零窗口报文,用tcp.analysis.window_update找到窗口更新报文。零窗口持续的时间越长,说明接收方应用处理越慢。如果零窗口一直不更新,可能是接收方应用卡死了。这时候需要检查接收方的应用状态和系统资源。7. 常见问题与排查技巧实录7.1 抓不到包或抓到的包不完整这是新手最常遇到的问题。可能的原因和排查方法:现象可能原因排查方法一个包都没有选错网卡看接口列表的流量波形,选活跃的网卡只有部分包捕获过滤器太严先去掉过滤器,抓完再用显示过滤器筛包不完整网卡硬件卸载关闭TSO/LRO,或在Wireshark里忽略校验和错误看不到应用层数据加密协议HTTPS流量是加密的,只能看到TCP层,看不到HTTP内容提示:如果抓HTTPS流量,你只能分析TCP层的行为,看不到HTTP请求和响应。要做应用层分析,需要配置SSLKEYLOGFILE或者使用其他方法。7.2 序列号和确认号看不懂这是概念问题,不是操作问题。记住几个要点:序列号是字节序号,不是报文序号SYN和FIN各占一个序列号确认号是累积确认,表示期望收到的下一个字节Wireshark默认显示相对序列号,ISN显示为0如果还是看不懂,找一个简单的HTTP请求,把每个报文的Seq、Ack、Len三个字段列出来,手动算一遍。算过一遍就明白了。7.3 重传和乱序分不清重传和乱序在Wireshark里都会显示为"异常的序列号",但它们的含义不同:重传:同一个序列号的数据被发送了多次,说明数据可能丢了乱序:序列号不连续,后面的报文先到了,说明网络路径上存在多路径Wireshark会自动标记这两种情况,但有时候会误判。判断的依据是时间和上下文。如果同一个序列号在短时间内出现多次,大概率是重传;如果序列号跳跃但每个只出现一次,大概率是乱序。7.4 窗口大小为什么一直是0零窗口说明接收方缓冲区满了。排查思路:检查接收方应用是否在处理数据,还是卡住了检查接收方的系统资源,CPU、内存是否正常检查接收方的TCP接收缓冲区设置,是否太小如果是自己写的应用,检查读取数据的逻辑是否有问题在Linux上,可以用ss -tln查看socket的接收队列和发送队列。如果Recv-Q很大,说明应用没有及时读取数据。7.5 实验报告怎么写才不像抄的这个问题很实际。我的建议是:不要只贴截图,要写你的分析过程。比如三次握手,不要只放三个包的截图,要写出:你抓的是什么流量,为什么选这个三个包的序列号和确认号分别是多少,为什么是这个值你观察到了什么异常(如果有),你是怎么判断的你对三次握手有了什么新的理解这样的报告才有价值,也才能体现出你真的动手做了实验,而不是复制粘贴。8. 从实验到实战:这些技能能用在什么地方做完这个实验,你获得的不只是几个截图,而是一种用报文验证协议行为的能力。这种能力在实际工作中有很多应用场景。排查网络性能问题:用户反馈某个接口很慢,你可以抓包看看是TCP重传多、窗口小、还是RTT高。每个指标对应不同的优化方向。调试分布式系统:微服务之间的调用超时,抓包能看到是连接建立慢、数据传输慢、还是对端处理慢。比看日志更直接。理解安全攻击:SYN Flood、RST攻击、会话劫持,这些攻击在Wireshark里都有明显的报文特征。理解了正常行为,才能识别异常行为。优化应用性能:通过观察TCP的行为,你可以判断是否需要调整Nagle算法、延迟确认、窗口大小等参数。这些调整对高并发应用的影响很大。我个人在实际工作中的体会是,抓包分析这项技能,入门容易精通难。工具的使用几天就能学会,但报文背后的协议逻辑和网络行为,需要长期的积累和思考。每次遇到网络问题,不要急着搜答案,先抓个包看看,往往能发现意想不到的线索。最后分享一个小技巧:Wireshark的"追踪TCP流"功能(Follow TCP Stream)可以把一条TCP连接的所有应用层数据拼在一起显示。分析HTTP请求响应的时候特别有用,能直接看到完整的交互内容。但要注意,这个功能只对未加密的流量有效,HTTPS流量看到的是乱码。