当前位置: 首页 > news >正文

Wireshark实战:从抓包到解析,深入理解TCP三次握手与四次挥手

1. 为什么需要抓包分析TCP协议?

很多开发者都有这样的困惑:明明代码逻辑没问题,但网络通信就是不稳定。这时候如果能直接看到底层的数据流动,问题往往迎刃而解。就像医生需要X光片诊断病情,我们通过Wireshark这个"网络X光机",可以直观观察TCP协议的工作细节。

我在排查一个线上故障时,发现客户端偶尔会卡在连接阶段。通过抓包发现,服务端有时会丢失第二次握手报文,最终定位到是防火墙配置问题。这种问题如果只看应用层日志,可能永远找不到根因。

TCP作为可靠的传输层协议,其核心机制就体现在三次握手和四次挥手过程中。理解这些交互细节,能帮助我们:

  • 准确诊断连接超时、重置等异常
  • 优化网络性能(如调整窗口大小)
  • 深入理解HTTP/MySQL等上层协议的基础

2. 实验环境搭建

2.1 准备测试程序

我们先准备最简单的TCP回显服务,服务端代码保存为EchoServer.java

import java.net.*; import java.io.*; public class EchoServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("Server started on port 8080"); Socket clientSocket = serverSocket.accept(); try (InputStream in = clientSocket.getInputStream(); OutputStream out = clientSocket.getOutputStream()) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } } }

客户端代码保存为EchoClient.java

import java.net.*; import java.io.*; public class EchoClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 8080); OutputStream out = socket.getOutputStream(); InputStream in = socket.getInputStream(); out.write("Hello TCP!".getBytes()); out.flush(); byte[] response = new byte[1024]; int len = in.read(response); System.out.println("Server echo: " + new String(response, 0, len)); socket.close(); } }

2.2 配置Wireshark抓包

  1. 启动Wireshark选择"Adapter for loopback traffic capture"
  2. 在过滤栏输入tcp.port == 8080,只捕获目标端口流量
  3. 先启动服务端java EchoServer,再启动客户端java EchoClient

注意:如果抓不到本地回环流量,可以改用127.0.0.1代替localhost,或者使用ncat等工具辅助

3. 三次握手深度解析

3.1 第一次握手:SYN报文

当客户端执行new Socket("localhost", 8080)时,抓包会看到类似这样的报文:

Frame 1: 62 bytes on wire Ethernet II Internet Protocol Version 4 Transmission Control Protocol Source Port: 54231 Destination Port: 8080 [SYN] Seq=0 Window Size: 65535 [TCP Options] Maximum Segment Size: 65495 Window Scale: 8 (multiply by 256) SACK Permitted

关键字段解读:

  • SYN标志:表示发起连接请求
  • Seq=0:初始序列号(实际是随机值,这里简化为0)
  • Win=65535:初始接收窗口大小
  • MSS=65495:声明自己能接收的最大报文段
  • WS=256:窗口缩放因子,用于后续扩大窗口

3.2 第二次握手:SYN+ACK报文

服务端收到SYN后,回复的报文如下:

Frame 2: 62 bytes Transmission Control Protocol Source Port: 8080 Destination Port: 54231 [SYN, ACK] Seq=0 Ack=1 Window Size: 65535 [TCP Options] MSS: 65495 Window Scale: 8 SACK Permitted

新增关键字段:

  • ACK标志:表示确认收到客户端SYN
  • Ack=1:期待下次收到Seq=1的数据(SYN占用1个序号)

3.3 第三次握手:ACK报文

客户端最后的确认报文:

Frame 3: 54 bytes Transmission Control Protocol Source Port: 54231 Destination Port: 8080 [ACK] Seq=1 Ack=1 Window Size: 262140 # 65535*4 (窗口缩放生效)

此时连接已建立,后续就可以传输数据。有趣的是,虽然SYN报文占用了序列号,但实际数据传输时并不会包含这个序号的数据。

4. 数据传输过程分析

4.1 发送数据:PSH+ACK报文

当客户端执行out.write()时,会看到:

Frame 4: 71 bytes Transmission Control Protocol [PSH, ACK] Seq=1 Ack=1 Len=10 Window Size: 262140 Data: "Hello TCP!"

关键点:

  • PSH标志:提示接收方应立即提交给应用层
  • Seq=1:延续握手结束时的序列号
  • Len=10:数据长度对应"Hello TCP!"的字节数

4.2 确认接收:ACK报文

服务端收到数据后回复纯ACK:

Frame 5: 54 bytes Transmission Control Protocol [ACK] Seq=1 Ack=11 Window Size: 262140

这里Ack=11表示已完整收到Seq=1~10的数据,期待下次从Seq=11开始。

4.3 服务端回显数据

服务端将数据原样返回时:

Frame 6: 71 bytes Transmission Control Protocol [PSH, ACK] Seq=1 Ack=11 Len=10 Data: "Hello TCP!"

注意虽然数据内容相同,但Seq/Ack编号是独立维护的。服务端的Seq从1开始,因为这是它第一次发送数据。

5. 四次挥手全流程

5.1 第一次挥手:FIN+ACK

客户端调用socket.close()时发送:

Frame 7: 54 bytes Transmission Control Protocol [FIN, ACK] Seq=11 Ack=11

FIN表示要关闭连接,同时ACK确认之前的数据。FIN和SYN一样会占用一个序列号。

5.2 第二次挥手:ACK

服务端立即回复确认:

Frame 8: 54 bytes Transmission Control Protocol [ACK] Seq=11 Ack=12

注意Ack=12表示确认了客户端的FIN(Seq=11 + 1)

5.3 第三次挥手:FIN+ACK

服务端也准备关闭时发送:

Frame 9: 54 bytes Transmission Control Protocol [FIN, ACK] Seq=11 Ack=12

5.4 第四次挥手:ACK

客户端最后确认:

Frame 10: 54 bytes Transmission Control Protocol [ACK] Seq=12 Ack=12

这里有个易错点:虽然双方都发送了FIN,但序列号空间是独立的,不会互相影响。

6. 常见问题排查技巧

在实际项目中,我经常用这些特征诊断问题:

  1. 连接失败:检查是否收到SYN的ACK回复。如果只有SYN没有响应,可能是防火墙拦截或服务未启动。

  2. 连接重置:收到RST标志通常表示对端socket已关闭却收到数据。

  3. 数据传输卡顿:观察窗口大小(Win)是否降为0,这可能触发了流控。

  4. 挥手异常:如果只有三次挥手,可能是对端开启了TCP快速断开(SO_LINGER)。

  5. 重传现象:相同Seq的报文重复出现,表明存在网络丢包。

建议抓包时配合使用Statistics > Flow Graph功能,可以直观看到报文交互时序。对于HTTPS等加密流量,可以通过ssl.handshake过滤器专门分析TLS握手过程。

http://www.jsqmd.com/news/550094/

相关文章:

  • STL到STEP转换终极指南:从3D打印到工程设计的无缝桥梁
  • 告别手点!用SAM-Veteran这个MLLM智能体,让AI像老手一样自动分割图片
  • 手把手教你用像素语言·维度裂变器:从入门到精通
  • 2026年工业/临时/户外/大型/移动/定制仓储篷房厂家推荐:常州春秋会展篷房全系解决方案 - 品牌推荐官
  • Atlas OS中Xbox应用0x89235107错误的完整解决方案
  • Mermaid声明式图表引擎技术架构评估报告
  • 三步掌握BilibiliDown:极速高效下载B站视频全攻略
  • Lucky Lillia Bot技术架构深度解析:OneBot 11协议在NTQQ平台的实现方案
  • 2026年芯片厂家实力推荐:珠海市芯动力科技,多领域专用芯片解决方案提供商 - 品牌推荐官
  • MATLAB画完图总被导师/同事吐槽看不懂?手把手教你用legend和grid on打造‘傻瓜式’数据可视化
  • UR5机械臂避坑指南:用Python版TOTG替代MoveIt的5个理由(附完整配置流程)
  • Verilog数字设计:深入对比两种Binary-to-BCD转换算法的硬件实现(附仿真对比)
  • MyBatisPlus项目实战:5分钟集成EasyTrans字典翻译(附避坑指南)
  • 从真人视频到虚拟偶像:OpenMMD如何用深度学习实现零门槛3D动画制作
  • 2026广州汽车租赁服务推荐:伟乐租车涵盖小车/商务车/中巴/大巴全系车型,满足多样化出行需求 - 品牌推荐官
  • CatBoost vs XGBoost:哪个更适合你的数据集?(含性能对比)
  • STM32F103C8T6驱动AS5600磁编码器:硬件IIC+DMA与软件IIC两种方案实测对比与避坑指南
  • Fusion 360 3D打印螺纹终极指南:告别打印失败,轻松创建完美螺纹
  • 2026年热转印滚筒机厂家推荐:东莞市高尚机械,滚筒热转印机器/烫画机全系供应 - 品牌推荐官
  • 从零到一:手把手教你用STM32F103和IR2104搭建单相全桥逆变器(附Buck电源LM5164选型)
  • GHelper:华硕ROG笔记本性能控制颠覆式工具,让硬件管理效率倍增
  • 从COBOL到现代编程:千年虫危机给我们的5个技术债务教训
  • 2026年板带轧制油厂家推荐:南京科润工业介质,全系轧制油产品供应与技术保障 - 品牌推荐官
  • OpenClaw+百川2-13B量化模型:3个提升效率的自动化脚本
  • 从零搭建船舶电力推进系统仿真:手把手教你玩转MATLAB电力王国
  • 用DINOv2和DPT头,手把手教你复现Depth Anything V3的深度估计模型(附代码避坑点)
  • Z-Image-Turbo安全部署:API访问控制实践
  • 停止健身房“赎罪”:把动作揉进日常,比发狠管用
  • 无损音质管理:解锁HiRes音乐收藏新体验 | 构建个人高品质音频库
  • 2026年液态硅胶注塑机厂家推荐:东莞市斯利科机械,lsr液态硅胶机/固转液设备全系列供应 - 品牌推荐官