资讯动态

Wireshark抓包分析TCP协议:从三次握手到重传机制实战

发布时间:2026/10/20 4:07:28 来源:尧图企业网站定制
1. 抓包之前先想清楚TCP实验到底在验证什么很多人做Wireshark的TCP实验打开软件就开始抓抓完对着一堆密密麻麻的包发呆不知道从哪看起。我刚开始接触的时候也是这样抓了上百个包最后只看出“哦有三次握手”然后就没了。问题出在哪儿出在动手之前没有想清楚这个实验到底要验证什么。TCP协议的核心机制其实就那么几个连接建立三次握手、数据传输序号与确认号、连接释放四次挥手、流量控制窗口大小、拥塞控制慢启动、拥塞避免、重传机制超时重传、快速重传。Wireshark实验的目的就是让你在真实的网络流量中亲眼看到这些机制是怎么运作的而不是停留在课本上的时序图里。这个实验适合谁网络方向的在校学生、准备网络相关认证的考生、刚入行的运维工程师以及任何想真正搞懂TCP而不是背概念的人。你不需要有很深的编程基础但需要了解IP地址、端口号、报文这些基本概念。如果连“客户端”和“服务端”谁先发包都分不清建议先补一下计算机网络的基础课。我个人的习惯是每次做TCP实验之前先在纸上画一遍预期的时间线——哪个包应该是SYN哪个应该是SYNACK哪个应该是ACK数据传输阶段序号应该怎么递增。画完之后再去抓包对照效率会高很多。这个习惯看起来笨但实测下来比漫无目的地翻包快得多。提示做TCP实验不需要真的去搭建一个复杂的网络环境。一台电脑一个能访问的远端服务加上Wireshark就够了。关键是你要能控制变量——比如你想观察三次握手就找一个干净的连接你想观察重传就人为制造丢包。2. 实验环境搭建与抓包策略2.1 工具准备与网卡选择Wireshark的安装没什么好说的官网下载对应系统的版本一路下一步就行。Windows下安装的时候会提示你装Npcap这个必须装它是底层抓包驱动不装的话Wireshark找不到网卡。安装过程中有一个选项叫“Restrict Npcap drivers access to Administrators only”如果你的电脑只有你自己用可以不勾选这样普通权限也能抓包省得每次都右键“以管理员身份运行”。装好之后打开Wireshark你会看到一列网卡接口。这里有个坑不要选“any”或者“所有接口”除非你明确知道自己要抓什么。选“any”会把所有网卡的流量混在一起噪音极大。正确的做法是选你实际用来上网的那块网卡——有线就选以太网无线就选WLAN。怎么确认看哪个网卡的流量曲线在跳动或者直接看IP地址和你ipconfig结果里一致的的那块就是。选好网卡之后先不要急着点开始。Wireshark的捕获选项里有一个“Capture filter”这个和后面要讲的“Display filter”是两码事。Capture filter是在抓包阶段就过滤不满足条件的包直接不抓好处是减少文件体积坏处是抓错了就没了。Display filter是抓完之后在界面上过滤不影响原始数据。对于TCP实验我建议抓包阶段不加过滤抓完再用Display filter筛选这样不会漏掉关键包。2.2 抓包时机的把握抓包时机这件事说起来简单但实际操作中很多人会错过关键帧。比如你想抓三次握手结果等你想起来点开始的时候连接已经建立完了。我的做法是先点开始抓包再去触发连接。具体来说如果你要访问某个网站先在Wireshark里点开始然后在浏览器里输入地址回车。这样SYN包一定能抓到。如果你要观察的是已经建立的连接上的数据传输那就在传输动作之前开始抓。比如你要观察文件下载的TCP流先点开始抓包再去点下载按钮。听起来是废话但我见过太多人抓完之后发现第一个包就是PSHACKSYN根本没抓到就是因为顺序反了。还有一个细节抓包文件要及时保存。Wireshark默认把抓到的包放在内存里如果你抓了很久不保存万一软件崩了或者你不小心关了数据就没了。我一般抓完一段就File - Save As存成pcapng格式这个格式比pcap支持更多元数据后续分析更方便。2.3 用Display Filter精准定位TCP流量抓完包之后面对成百上千个包第一步就是过滤。Wireshark的Display filter语法很灵活下面这几个是我做TCP实验时最常用的过滤表达式作用使用场景tcp只显示TCP包排除ARP、DNS等干扰tcp.port 80只显示80端口的TCP包观察HTTP流量tcp.port 443只显示443端口的TCP包观察HTTPS流量ip.addr 192.168.1.100只显示与指定IP相关的包锁定特定主机tcp.flags.syn 1只显示SYN标志位置1的包快速定位握手包tcp.flags.fin 1只显示FIN标志位置1的包快速定位挥手包tcp.analysis.flags显示Wireshark标记的异常包排查重传、乱序等问题这些过滤器可以组合使用比如tcp.port 80 tcp.flags.syn 1就能精确找到80端口上的SYN包。注意逻辑运算符Wireshark用的是与、||或、!非和很多编程语言一样。但如果你写tcp.port 80 or 443这是错的必须写成tcp.port 80 || tcp.port 443。提示Display filter输入框变绿表示语法正确变红表示语法有误。如果你不确定某个字段名怎么写可以在包详情面板里右键某个字段选择“Apply as Filter”Wireshark会自动帮你生成正确的过滤表达式。这个功能对新手特别友好。3. 三次握手从SYN到ACK的完整拆解3.1 三次握手的包长什么样三次握手是TCP连接建立的必经过程也是Wireshark实验里最容易观察到的现象。找一个干净的HTTP网站比如某个不设防的静态页面在浏览器里访问它同时用Wireshark抓包。抓完之后用tcp.flags.syn 1 || tcp.flags.ack 1过滤你会看到类似这样的序列No. Source Destination Protocol Info 1 192.168.1.100 93.184.216.34 TCP 49152 → 80 [SYN] Seq0 Win64240 Len0 MSS1460 2 93.184.216.34 192.168.1.100 TCP 80 → 49152 [SYN, ACK] Seq0 Ack1 Win65535 Len0 MSS1460 3 192.168.1.100 93.184.216.34 TCP 49152 → 80 [ACK] Seq1 Ack1 Win64240 Len0这三行就是三次握手的全部内容。第一行是客户端发起的SYN包第二行是服务端回的SYNACK包第三行是客户端再回的ACK包。注意看Info列里的Seq和Ack值第一个包的Seq0相对序号第二个包的Ack1第三个包的Seq1、Ack1。这个递增关系就是TCP可靠传输的基础。点开第一个SYN包的详情面板展开“Transmission Control Protocol”这一层你会看到很多字段。其中几个关键字段需要重点关注Source Port客户端随机选择的端口通常是49152到65535之间的一个值。这个范围叫“动态端口”或“私有端口”IANA规定的。Destination Port服务端监听的端口HTTP是80HTTPS是443。Sequence Number初始序号ISNWireshark默认显示相对序号所以是0。如果关掉相对序号显示你会看到一个很大的随机数。Flags这里显示的是0x002 (SYN)表示SYN标志位置1。Options展开这一层你会看到MSS、SACK Permitted、Window Scale等选项。这些是TCP的可选参数在握手阶段协商。3.2 为什么是三次而不是两次或四次这个问题面试经常问但很多人背答案没有真正理解。从Wireshark的抓包结果来看三次握手的本质是双方各自确认自己和对方的收发能力都正常。第一次握手客户端发SYN服务端收到。服务端能确认“客户端发送能力正常我的接收能力正常”。但客户端还不知道服务端能不能收到、能不能发。第二次握手服务端回SYNACK客户端收到。客户端能确认“我的发送能力正常服务端的接收能力正常服务端的发送能力正常我的接收能力正常”。到这里客户端已经全确认了但服务端还缺一个确认——它不知道客户端有没有收到自己的SYNACK。第三次握手客户端回ACK服务端收到。服务端确认“我的发送能力正常客户端的接收能力正常”。至此双方全确认。两次不够因为服务端缺最后一次确认四次多余因为第二次握手已经把SYN和ACK合并了。在Wireshark里你能直观看到这个合并第二个包的Flags字段同时有SYN和ACK两个标志位这就是“捎带确认”的体现。3.3 握手阶段的常见异常正常情况下三次握手一气呵成但在Wireshark里你可能会看到一些异常情况。下面这张表是我在实际抓包中遇到过的几种异常现象Wireshark表现可能原因排查方向SYN无响应只有SYN包没有SYNACK服务端未监听、防火墙拦截检查目标端口是否开放SYN被拒绝收到RSTACK服务端端口关闭确认服务是否启动重复SYN同一个SYN发多次第一次SYN丢失或ACK丢失检查网络丢包率SYNACK重传服务端重发SYNACK客户端ACK丢失检查客户端网络半开连接只有SYN和SYNACK无最终ACK客户端异常退出检查客户端状态其中RST包值得单独说一下。RST是TCP的复位标志当一方收到不期望的包时就会发RST。比如你访问一个没有服务监听的端口服务端会直接回RSTACK而不是忽略。在Wireshark里看到RST基本可以确定连接建立失败了。注意有些防火墙会伪造SYNACK来欺骗客户端让客户端以为连接建立了但实际上后续数据都被拦截。这种情况在Wireshark里表现为握手正常但数据传输阶段没有响应。如果你遇到“能握手但传不了数据”的情况可以往这个方向排查。4. 数据传输序号、确认号与窗口的协同4.1 序号与确认号的递增规律三次握手之后连接进入数据传输阶段。这个阶段最核心的观察点就是序号Sequence Number和确认号Acknowledgment Number的变化。TCP把数据看成字节流每个字节都有一个序号。发送方告诉对方“我这次发的数据从第N个字节开始”接收方回“我已经收到第NM个字节了下次给我发第NM1个”。在Wireshark里默认显示的是相对序号也就是相对于初始ISN的偏移量。比如握手时ISN是0那么第一个数据字节的序号就是1。假设客户端发了100字节的数据Seq1Len100那么下一个包的Seq就是101。服务端回的ACK包里Ack101表示“1到100我都收到了下次发101”。这里有一个容易混淆的点Len0的包不消耗序号。纯ACK包、SYN包、FIN包的Len都是0它们的序号不递增。只有携带数据的包才会让序号增加。你在Wireshark里看到Seq不变但Ack在变的包基本都是纯ACK。我建议在Wireshark里打开“Statistics - Flow Graph”选择“TCP flow”这样能直观看到双方交互的时序图。每个包的Seq和Ack都标在箭头上比在包列表里逐个看要清楚得多。4.2 窗口大小与流量控制TCP的流量控制靠的是滑动窗口机制。接收方在每个ACK包里告诉发送方“我还能接收多少字节”这个值就是窗口大小Window Size。发送方根据这个值调整发送速率确保不会把接收方的缓冲区撑爆。在Wireshark的TCP详情面板里Window Size字段显示的就是当前通告的窗口大小。但要注意如果握手时协商了Window Scale选项实际窗口大小是“Window Size值 × 2^Scale因子”。比如Window Size显示65535Scale是7实际窗口就是65535 × 128 8388480字节。窗口大小的变化能反映很多信息。如果窗口突然变小说明接收方处理不过来缓冲区快满了如果窗口变成0说明接收方缓冲区完全满了发送方必须停止发送这就是零窗口。零窗口之后发送方会定期发窗口探测包询问接收方“现在能收了吗”。在Wireshark里零窗口和窗口探测都有特殊的标记用tcp.analysis.zero_window可以过滤出来。4.3 实操观察一次完整的文件传输光看理论不够我带你走一遍完整的观察流程。找一个提供文件下载的网站或者自己用Python起一个简单的HTTP服务放一个大一点的文件比如几十MB然后在Wireshark里选好网卡点开始抓包。在浏览器里访问那个文件开始下载。下载完成后停止抓包。用tcp.port 80过滤假设是HTTP。找到三次握手的第一个SYN包右键选择“Follow - TCP Stream”。Follow TCP Stream会把整个TCP连接的所有包按顺序展示出来左边是客户端发的右边是服务端发的。你能看到HTTP请求头、响应头、以及文件数据的传输过程。注意观察数据传输阶段的包大小通常会是MSS的整数倍比如1460、2920、4380这样。最后一个包可能小于MSS因为文件大小不一定刚好是MSS的整数倍。在Follow TCP Stream的窗口里你还能看到Wireshark自动计算的吞吐量、丢包率等统计信息。这些数据对于分析传输性能很有帮助。如果丢包率高说明网络质量差如果吞吐量远低于带宽可能是窗口太小或者有拥塞。提示Follow TCP Stream默认显示的是ASCII格式如果传输的是二进制文件会显示乱码。这时候可以切换到“Raw”或“Hex Dump”视图。不过对于分析TCP行为来说内容是什么不重要重要的是包的序号、确认号和窗口变化。5. 四次挥手与连接释放5.1 四次挥手的标准流程数据传输完成后连接需要释放。TCP的释放过程是四次挥手因为TCP连接是全双工的每个方向都需要单独关闭。标准流程如下主动关闭方发FIN表示“我没有数据要发了”。被动关闭方回ACK表示“我知道你没数据要发了”。被动关闭方发FIN表示“我也没有数据要发了”。主动关闭方回ACK表示“我知道你也没数据要发了”。在Wireshark里用tcp.flags.fin 1过滤你能看到FIN包。注意FIN包也消耗一个序号虽然它的Len是0。这是因为FIN标志位在逻辑上占一个字节的位置接收方回的ACK会确认这个FIN。为什么需要四次而不是三次因为被动关闭方收到FIN后可能还有数据没发完不能立即发FIN。它先回一个ACK等数据发完了再发FIN。如果被动关闭方也没有数据要发了ACK和FIN可以合并变成三次挥手。在Wireshark里这种情况也能看到第二个包同时有ACK和FIN标志。5.2 TIME_WAIT状态的意义四次挥手的最后一步主动关闭方发完ACK后会进入TIME_WAIT状态等待2MSLMaximum Segment Lifetime报文最大生存时间后才真正关闭连接。在Wireshark里你抓不到TIME_WAIT本身因为它是内核状态不是网络包。但你能通过端口复用的行为间接观察到。TIME_WAIT的存在有两个原因一是确保最后一个ACK能到达被动关闭方如果ACK丢了被动关闭方会重发FIN主动关闭方还能响应二是让本次连接的所有报文在网络中消失避免影响后续使用相同端口的新连接。在服务器上netstat -an | grep TIME_WAIT能看到大量TIME_WAIT状态的连接这是正常现象。但如果TIME_WAIT过多导致端口耗尽就需要调整内核参数了。不过这是运维层面的问题Wireshark实验里不需要深入。5.3 异常释放RST包的使用场景除了正常的四次挥手TCP还支持用RST包强制释放连接。RST包的特点是不需要确认收到即生效。常见的使用场景包括访问未监听的端口服务端回RST。连接超时一方主动发RST。应用程序异常退出操作系统代发RST。收到不期望的包比如没有握手就收到数据。在Wireshark里RST包的Flags字段显示为0x004 (RST)。如果RST包同时带ACK显示为0x014 (RST, ACK)。RST包通常意味着连接异常终止如果你在抓包中看到大量RST说明网络或应用层面有问题。注意有些中间设备如负载均衡器会主动发RST来关闭空闲连接。这种情况下的RST是正常行为不需要排查。判断方法是看RST的发送方是谁——如果是你认识的服务器IP可能是应用问题如果是未知IP可能是中间设备。6. 重传与异常分析从抓包中定位问题6.1 超时重传与快速重传TCP保证可靠传输的核心机制是重传。当发送方在一定时间内没有收到ACK就会重传数据。这个时间叫RTORetransmission Timeout是根据RTT往返时间动态计算的。在Wireshark里超时重传的包会被标记为[TCP Retransmission]颜色通常是黑色背景红色文字。除了超时重传还有快速重传。当接收方收到乱序的包时会立即发送重复ACKDuplicate ACK告诉发送方“我期望的序号是X但我收到了X之后的包”。发送方连续收到3个重复ACK就认为X丢了立即重传X不用等超时。快速重传在Wireshark里标记为[TCP Fast Retransmission]。这两种重传的区别很重要超时重传说明网络状况很差RTT波动大快速重传说明有零星丢包但网络整体还行。在Wireshark的“Expert Information”里能看到重传的统计如果重传率超过1%就需要关注了。6.2 重复ACK与乱序重复ACK是接收方对乱序包的响应。假设发送方发了Seq1、Seq1461、Seq2921三个包但Seq1461丢了接收方收到Seq1后回Ack1461收到Seq2921后发现不是期望的1461又回Ack1461。这个重复的Ack1461就是重复ACK。在Wireshark里重复ACK会被标记为[TCP Dup ACK]。如果你看到大量重复ACK说明网络有乱序或丢包。乱序和丢包的区别在于乱序时后续的包最终会到达只是顺序不对丢包时某个包彻底没了必须重传。Wireshark有一个很好用的功能叫“TCP Stream Graphs - Time Sequence (Stevens)”能把序号随时间的变化画成图。正常传输是一条斜向上的直线如果有丢包或重传线上会出现平段或回退。这个图对于快速判断网络质量非常直观。6.3 常见问题速查表下面这张表是我在做TCP实验和实际运维中总结的常见问题速查表遇到异常时可以对照排查Wireshark标记含义常见原因解决方向[TCP Retransmission]超时重传网络拥塞、链路质量差检查带宽和丢包率[TCP Fast Retransmission]快速重传零星丢包检查链路稳定性[TCP Dup ACK]重复确认乱序或丢包区分乱序和丢包[TCP Out-of-Order]乱序多路径转发通常无需处理[TCP ZeroWindow]零窗口接收方缓冲区满检查接收方性能[TCP Window Full]发送方窗口满接收方通告窗口小调整窗口大小[TCP Keep-Alive]保活探测连接空闲过久正常现象[TCP RST]连接复位端口关闭、异常退出检查应用状态这张表建议收藏下次抓包遇到不认识的标记先查表再深入分析。6.4 我踩过的坑与实操心得说几个我在做TCP实验时踩过的坑希望能帮你省点时间。第一个坑抓包位置不对。我一开始在虚拟机上抓包结果发现抓到的包和真实网络行为对不上。后来才明白虚拟机的网卡是虚拟的流量经过NAT转换后源IP和端口都变了。如果你要观察真实的TCP行为尽量在物理机上抓或者把虚拟机网卡设成桥接模式。第二个坑忽略了时间戳。Wireshark默认显示的是相对时间第一个包是0秒后面的包显示相对于第一个包的时间。这个设置对于分析RTT很方便但如果你想看绝对时间需要改一下视图设置。我建议在分析重传时用相对时间分析连接建立时间时用绝对时间。第三个坑过滤太早。有一次我想观察三次握手就在Capture filter里写了tcp.flags.syn 1结果只抓到了SYN包SYNACK和ACK都没抓到。因为Capture filter是在抓包阶段过滤的不满足条件的包直接丢弃。正确的做法是抓包阶段不过滤抓完再用Display filter筛选。第四个坑忘了关相对序号。Wireshark默认显示相对序号这对于初学者很友好但有时候你需要看真实的ISN。在“Edit - Preferences - Protocols - TCP”里可以关掉“Relative sequence numbers”。关掉之后你会看到真实的随机ISN对于理解TCP的安全性设计有帮助。第五个坑抓包文件太大。如果你抓了一个小时的全量流量文件可能有好几个GBWireshark打开会很卡。我的做法是用Capture filter限制抓包范围比如只抓特定IP或特定端口。虽然前面说抓包阶段不过滤但那是对初学者而言。等你熟练了知道自己在抓什么就可以用Capture filter提高效率了。提示Wireshark的“Statistics - Conversations”能看到所有TCP会话的统计信息包括每个会话的包数、字节数、持续时间。这个功能对于快速定位异常会话很有用。比如你发现某个会话的重传率特别高就可以重点分析那个会话。7. 从实验到实战TCP分析能力的迁移做完Wireshark的TCP实验你获得的不只是几个截图和一份报告而是一种从原始流量中还原协议行为的能力。这种能力在实际工作中有很多应用场景。比如线上服务响应变慢你可以抓包分析是不是TCP重传导致的比如用户反馈下载速度慢你可以看窗口大小是不是被限制了比如怀疑有网络攻击你可以看SYN包的数量是不是异常。这些场景的核心分析方法和你在实验里做的是一样的抓包、过滤、看序号和标志位、定位异常。我个人的经验是TCP分析能力的关键不在于记住多少字段而在于建立一套排查思路。遇到问题先问自己连接建立了吗握手有没有异常数据传输阶段有没有重传窗口有没有变化连接是怎么释放的沿着这条线走下来大部分TCP层面的问题都能定位。最后分享一个小技巧如果你经常做TCP分析可以把自己常用的Display filter保存成按钮放在Wireshark的过滤栏旁边。这样下次用的时候一键就能过滤不用每次手敲。具体操作是Edit - Preferences - Filter Expressions添加你常用的表达式并命名。我保存了“握手包”“重传包”“零窗口”“RST包”四个按钮用起来很顺手。这个实验后续还可以这样扩展把抓包环境换成无线网络观察无线环境下的TCP行为有什么不同或者用tc命令人为制造延迟和丢包观察TCP的拥塞控制响应再或者分析HTTPS流量的TCP行为虽然内容加密了但TCP层的序号、确认号、窗口还是可见的。这些扩展方向都能让你对TCP的理解更深一层。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑