首页 / 资讯中心 / 文章详情

TCP抓包实验完全指南:从三次握手到四次挥手实战分析

TCP抓包实验完全指南:从三次握手到四次挥手实战分析 ★ FEATURED ARTICLE
1. 抓包实验到底在抓什么先搞清楚TCP的“对话逻辑”很多人第一次做TCP抓包实验打开Wireshark看到满屏滚动的数据包第一反应是懵的——这么多行哪一行才是我要的其实问题出在动手之前没想清楚一件事TCP抓包的本质是还原一次完整的对话过程。就像你在旁边偷听两个人打电话你要听的不是某一个字而是“谁先开口、说了什么、对方怎么回应、什么时候挂断”这一整套流程。TCP协议的核心机制可以用一句话概括面向连接的、可靠的、基于字节流的传输协议。这三个定语分别对应三次握手面向连接、确认重传可靠、序号与窗口字节流。抓包实验的目的就是把这几个抽象概念变成你肉眼能看到的真实数据包。具体来说一次典型的TCP抓包实验需要你完成以下目标捕获一次完整的TCP连接生命周期包括三次握手建立连接、数据传输、四次挥手断开连接识别关键字段序列号Sequence Number、确认号Acknowledgment Number、标志位Flags、窗口大小Window Size观察TCP的可靠传输机制确认应答、超时重传、滑动窗口理解端口号与IP地址在连接中的作用这个实验适合谁如果你是计算机网络课程的学生这是必做的经典实验如果你是刚入行的运维或后端开发抓包是你排查网络问题的基本功哪怕你只是对“网线那头到底发生了什么”感到好奇这个实验也能给你一个非常直观的答案。我见过太多人做这个实验的方式是打开Wireshark随便抓一堆包然后对着屏幕发呆。问题不在于工具不会用而在于没有带着问题去抓包。你要先有一个明确的场景——比如“我要访问一个网页看看TCP是怎么建立连接的”——然后围绕这个场景去过滤、去分析。下面我就按这个思路把整个实验从设计到实操到排错完整地拆一遍。2. 实验前的环境搭建与工具选型2.1 Wireshark安装与网卡选择Wireshark是跨平台的Windows、macOS、Linux都能装。官网直接下载对应版本即可安装过程一路下一步没什么坑。但有一个点需要注意Windows下安装时会提示你安装Npcap这是抓包驱动的核心组件必须装。如果你跳过了这一步打开Wireshark会发现一个网卡都列不出来。安装完成后打开Wireshark你会看到一张网卡列表。这里有个新手最容易踩的坑选错网卡。比如你用的是Wi-Fi上网却选了以太网网卡那抓到的包数量是零。怎么判断该选哪个看网卡名称旁边的实时流量波形图——哪条波形在跳动就说明那个网卡有数据在跑。提示如果你不确定哪块网卡在承载流量可以先随便选一个点开始抓包看有没有包进来。没有的话换一个再试。别在这个环节纠结太久。另外如果你在虚拟机里做实验比如VMware或VirtualBox网卡选择会更复杂一些。虚拟机的网络模式NAT、桥接、仅主机决定了你抓到的包长什么样。做TCP抓包实验建议用桥接模式这样虚拟机的网络行为和一台独立主机基本一致抓到的包最接近真实场景。2.2 抓包过滤器的选择BPF还是显示过滤器Wireshark有两套过滤系统新手经常搞混过滤类型使用时机语法示例特点捕获过滤器BPF开始抓包之前tcp port 80直接丢弃不匹配的包减少文件体积显示过滤器抓包过程中或之后tcp.port 80只影响显示不影响已捕获的数据我的建议是实验阶段优先用显示过滤器。原因很简单——捕获过滤器一旦设错该抓的包没抓到你得重来显示过滤器设错了改一下就行数据还在。等你对流量特征非常熟悉了再用捕获过滤器来精简数据。常用的显示过滤器语法你至少得记住这几条tcp // 只看TCP包 tcp.port 80 // 只看80端口的TCP包 tcp.flags.syn 1 // 只看SYN标志位置1的包握手包 ip.addr 192.168.1.100 // 只看与某个IP相关的包 tcp.stream eq 0 // 只看第0号TCP流最后一条tcp.stream eq N是分析TCP连接的利器。Wireshark会自动给每一条完整的TCP连接分配一个流编号你用这个过滤器就能把一次连接的所有包单独拎出来看非常清爽。2.3 实验拓扑的设计做TCP抓包实验不需要复杂的网络拓扑。最简单的方案是一台机器同时充当客户端和服务端通过本地回环地址127.0.0.1通信。但回环接口的抓包有个问题——Wireshark在Windows下默认抓不到回环流量需要额外安装Npcap的回环适配器或者用其他手段。所以我更推荐另一种方案两台机器一台跑服务端一台跑客户端通过局域网通信。如果你只有一台机器可以用虚拟机开两台或者一台物理机加一台虚拟机。这种方案的好处是抓到的包就是真实的网络流量没有回环接口的那些特殊处理。服务端用什么最简单的选择是Python自带的http.server模块一行命令就能起一个HTTP服务python -m http.server 8080客户端用浏览器或者curl访问这个服务就行。HTTP底层就是TCP所以这个场景天然包含完整的TCP连接过程。如果你想让实验更纯粹一点不想被HTTP协议的细节干扰也可以自己写一个简单的TCP客户端和服务端。Python的socket库几行代码就能搞定# 服务端 import socket s socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((0.0.0.0, 9999)) s.listen(1) conn, addr s.accept() data conn.recv(1024) print(收到:, data) conn.send(bACK from server) conn.close()# 客户端 import socket c socket.socket(socket.AF_INET, socket.SOCK_STREAM) c.connect((服务端IP, 9999)) c.send(bHello TCP) resp c.recv(1024) print(响应:, resp) c.close()这种自定义的TCP通信抓到的包最干净没有HTTP头部那些干扰信息非常适合用来观察三次握手和四次挥手的细节。3. 三次握手抓包分析从SYN到ACK的完整还原3.1 抓包前的准备工作在开始抓包之前先把服务端跑起来Wireshark也打开并选好网卡但先不要点开始。为什么因为你要确保抓到的第一个包就是SYN包这样整个连接过程才是完整的。操作顺序应该是这样的服务端启动监听端口比如9999Wireshark选好网卡设置显示过滤器为tcp.port 9999点击开始抓包客户端发起连接观察Wireshark中出现的包这个顺序很关键。如果你先启动客户端再开Wireshark可能SYN包已经过去了你抓到的就是不完整的连接。3.2 三次握手的包序列解读正常情况下你会在Wireshark中看到类似这样的序列序号源地址目的地址标志位说明1客户端服务端SYN客户端请求建立连接2服务端客户端SYN, ACK服务端同意并确认3客户端服务端ACK客户端确认这三个包就是经典的三次握手。下面逐个拆解每个包的细节。第一个包SYN展开Wireshark的TCP协议树你会看到几个关键字段Source Port客户端随机选择的一个端口通常是49152以上的高位端口Destination Port服务端监听的端口这里是9999Sequence Number客户端随机生成的初始序列号比如Seq0Wireshark默认显示相对序列号FlagsSYN标志位置1Window Size客户端告诉服务端自己的接收窗口大小这个包的含义是“我想跟你建立连接我的初始序列号是X我的接收窗口是Y。”第二个包SYNACK服务端的回应包关键字段Sequence Number服务端自己的初始序列号比如Seq0Acknowledgment NumberAck1即客户端的序列号加1FlagsSYN和ACK同时置1Window Size服务端的接收窗口大小这个包的含义是“我同意建立连接我的初始序列号是Z我确认收到你的序列号X期待你下一个字节是X1。”第三个包ACK客户端的最终确认Sequence NumberSeq1Acknowledgment NumberAck1Flags只有ACK置1这个包的含义是“我确认收到你的序列号Z期待你下一个字节是Z1。”到这里连接建立完成双方都确认了对方的序列号起点。3.3 为什么是三次而不是两次或四次这个问题面试经常问但很多人背答案不理解。用抓包的结果来解释就非常直观两次不够如果只有前两次握手服务端发送了SYNACK之后就认为连接建立了但客户端可能根本没收到这个包。如果客户端没收到它不会发送第三个ACK服务端却已经开始等待数据了——这就造成了服务端资源的浪费。四次多余服务端的SYN和ACK可以合并成一个包发送因为它们是同一时刻发出的没有必要拆成两个。所以三次握手的设计目标是让双方都确认自己和对方的发送、接收能力都正常。第一个包确认了客户端的发送能力第二个包确认了服务端的发送和接收能力第三个包确认了客户端的接收能力。实操心得在Wireshark中你可以右键点击某个包选择“Follow TCP Stream”Wireshark会自动把这条连接的所有包过滤出来并且按方向着色显示。这个功能在分析多条并发连接时特别好用。4. 数据传输与四次挥手连接的生命周期全貌4.1 数据传输阶段的观察要点三次握手完成后连接进入数据传输阶段。在这个阶段你需要重点观察以下几个现象序列号与确认号的递增规律。每发送一个字节的数据序列号就加1。比如客户端发送了10个字节的数据Seq1那么下一个包的Seq就是11。服务端回复的Ack也会相应变成11表示“我已经收到了前10个字节期待第11个字节”。窗口大小的动态变化。Window Size字段反映了接收方当前的缓冲区剩余空间。如果接收方处理数据的速度跟不上发送方窗口会逐渐缩小甚至变成0——这就是零窗口发送方会暂停发送直到接收方通告一个非零窗口。延迟确认与Nagle算法。你可能会发现有时候发送方连续发了两个小包接收方只回了一个ACK。这是TCP的延迟确认机制在起作用——接收方不会每收到一个包就立刻回复而是等一小段时间通常200ms看有没有更多数据可以一起确认。Nagle算法则是在发送方起作用它会把小数据攒起来一起发减少网络上的小包数量。这两个机制在抓包时的表现就是你看到的数据包序列不是严格的“一发一收”而是有延迟、有合并的。这不是bug是TCP在效率和实时性之间做的权衡。4.2 四次挥手的完整过程数据传输结束后连接需要断开。TCP的断开过程是四次挥手序号方向标志位说明1主动关闭方 → 被动关闭方FIN, ACK我没有数据要发了2被动关闭方 → 主动关闭方ACK我知道了3被动关闭方 → 主动关闭方FIN, ACK我也没有数据要发了4主动关闭方 → 被动关闭方ACK我知道了连接关闭为什么挥手是四次而握手是三次因为TCP是全双工的每个方向的数据流需要单独关闭。主动关闭方发送FIN只表示“我这个方向没有数据了”但对方可能还有数据要发所以不能把ACK和FIN合并。在Wireshark中你会看到FIN包和普通的ACK包长得差不多区别就在Flags字段里FIN标志位被置1了。最后一个ACK包发出后主动关闭方会进入TIME_WAIT状态等待2MSL报文最大生存时间的两倍通常60秒才真正释放连接。注意如果你在抓包时看到大量TIME_WAIT状态的连接不要慌这是正常现象。但如果TIME_WAIT连接数量异常多可能说明你的程序频繁地建立和断开连接需要考虑使用连接池来复用连接。4.3 用IO图表直观展示吞吐量Wireshark自带一个很好用的功能统计 → IO图表。你可以用它来绘制一段时间内的吞吐量曲线。操作步骤抓包进行中或抓包结束后点击菜单栏“统计”选择“IO图表”在图表设置中Y轴单位选择“Bytes”或“Bits”可以添加多条曲线分别对应不同的过滤器这个图表能帮你直观地看到什么时候数据传输最密集、有没有突然的流量中断可能对应重传、窗口变化对吞吐量的影响。我经常用这个功能来给学生展示“为什么窗口大小会影响传输速度”——图表上看得一清二楚。5. 常见问题与排查技巧实录5.1 抓不到包怎么办这是新手遇到最多的问题。排查思路按以下顺序来第一步确认网卡选对了。回到Wireshark主界面看网卡列表的波形图有没有在跳动。没有跳动说明这块网卡没有流量换一块。第二步确认过滤器没写错。如果你设了tcp.port 9999但实际通信用的是8080端口那当然什么都看不到。先把过滤器清空看看有没有包再逐步加过滤条件。第三步确认流量确实经过了这块网卡。如果你在虚拟机里抓包虚拟机的流量可能走的是虚拟网卡而不是你选的那块物理网卡。检查虚拟机的网络模式设置。第四步检查权限。Linux下抓包需要root权限或者将用户加入wireshark组。Windows下通常没这个问题但如果你用的是公司电脑可能有安全软件拦截了抓包驱动。5.2 抓到重复包或乱序包Wireshark中偶尔会看到TCP Retransmission重传或TCP Out-of-Order乱序的标记。这不一定是网络故障可能是以下原因抓包位置不对如果你在发送端抓包看到的重传可能是网卡驱动层面的重传实际网络并没有丢包网卡卸载功能现代网卡支持TSO、LRO等卸载功能会把大的数据段拆分成多个小包再发送抓包工具看到的是拆分前的状态导致看起来像乱序真实的网络丢包如果重传包确实是因为没收到ACK而触发的那说明网络中间确实有丢包判断方法看重传包的时间间隔。如果是几毫秒内的重传多半是抓包位置或网卡卸载导致的假象如果是几百毫秒甚至更长的重传那大概率是真实丢包。5.3 常见问题速查表问题现象可能原因解决方法抓不到任何包网卡选错换网卡看波形图只有单向流量过滤器方向限制检查过滤器是否限制了源或目的看不到三次握手抓包开始太晚先开Wireshark再发起连接大量TCP Retransmission真实丢包或网卡卸载换抓包位置关闭网卡卸载功能窗口大小始终为0接收方缓冲区满检查接收方程序是否在处理数据连接建立后立刻断开服务端程序异常检查服务端日志和端口监听状态5.4 几个容易被忽略的细节相对序列号 vs 绝对序列号。Wireshark默认显示相对序列号从0开始这样看起来更直观。但如果你需要和RFC文档对照可能需要切换到绝对序列号。在TCP协议首选项里可以改。时间戳的精度。Wireshark默认的时间精度是秒对于分析TCP的RTT往返时间来说太粗了。建议在“视图 → 时间显示格式”中改成“毫秒”或“微秒”。着色规则。Wireshark默认有一套着色规则比如黑色背景表示重传包红色表示异常包。你可以在“视图 → 着色规则”中查看和自定义。我习惯把SYN包设成绿色FIN包设成蓝色这样一眼就能看出连接的起止位置。6. 从抓包实验延伸到真实排障场景6.1 用抓包定位连接超时问题真实工作中你可能会遇到“客户端连接服务端超时”的问题。这时候抓包是最直接的排查手段。在客户端抓包如果你看到SYN包发出去了但没有收到SYNACK那说明服务端没在监听那个端口中间有防火墙拦截了服务端负载过高来不及响应如果收到了SYNACK但客户端没有发出最后的ACK那可能是客户端程序的问题。如果三次握手完成了但数据传输阶段卡住那就要看窗口大小和重传情况。6.2 分析TCP重传与网络质量重传率是衡量网络质量的重要指标。在Wireshark中你可以用tcp.analysis.retransmission过滤器来筛选所有重传包然后和总包数对比算出重传率。一般来说重传率低于0.1%网络质量很好重传率在0.1%到1%之间可以接受但需要关注重传率超过1%网络存在问题需要排查排查方向包括链路质量、中间设备负载、MTU不匹配导致的分片等。6.3 抓包实验的进阶方向如果你已经掌握了基本的TCP抓包分析可以往以下几个方向深入TLS握手分析。HTTPS的TLS握手是在TCP连接建立之后进行的你可以抓包观察Client Hello、Server Hello、证书交换等过程。不过TLS加密后的应用数据是看不到明文的只能看到握手阶段。HTTP/2和QUIC。HTTP/2在单个TCP连接上多路复用多个请求抓包时你会看到多个流交织在一起。QUIC则基于UDP完全绕开了TCP抓包分析的方法完全不同。性能调优。通过抓包分析RTT、窗口大小、重传率等指标可以定位应用程序的网络性能瓶颈。比如如果发现窗口经常变成0说明接收方处理太慢需要优化接收端的代码。我个人在实际操作中的体会是抓包这件事工具的使用只占三成七成在于你对协议的理解和排查思路。你脑子里有了“正常应该是什么样”的预期才能从一堆包里面快速找到“不正常”的那个。所以每次抓包之前先问自己一句我预期看到什么如果看到的和预期不一样差异在哪里这个差异能说明什么问题带着问题去抓包比漫无目的地抓一堆包然后慢慢翻效率要高得多。
阅读完成 · 觉得有帮助?
咨询建站