计算机网络学习笔记:Wireshark观察TCP通信

文章目录


前言

Wireshark是一款功能强大的网络抓包和协议分析工具,用于实时捕获和解析网络通信数据,帮助用户诊断网络问题、分析协议细节或进行安全审计。

本篇将用Wireshark工具对TCP通信案例进行抓包,分析三报文握手四报文挥手

一、前置准备

服务端案例工程:

java 复制代码
public class BIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(1848);
        System.out.println("EchoServer started on port 1848");

        //阻塞
        Socket clientSocket = serverSocket.accept();

        handleClient(clientSocket);

    }

    private static void handleClient(Socket clientSocket) {
        try(OutputStream out = clientSocket.getOutputStream();
            InputStream in = clientSocket.getInputStream()){
            byte[] bytes = new byte[1024];
            int len;
            while ((len = in.read(bytes))!= -1){
                out.write(bytes, 0, len);
                out.flush(); // 回显
            }
        }catch (Exception e){
            System.out.println("Client disconnected");
        }

    }
}

客户端案例工程:

java 复制代码
public class BIOClient {
    public static void main(String[] args) throws IOException {


        Socket socket = new Socket("localhost", 1848);
        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();

        out.write(("Hello Server:" + Thread.currentThread().getName()).getBytes());
        out.flush();

        byte[] buffer = new byte[1024];
        int len = in.read(buffer);
        System.out.println("Server Echo: " + new String(buffer, 0, len));

        socket.close();


    }
}

Wireshark工具设置,选择Adapter for loopback traffic capture

设置抓包过滤选项,为案例中的端口号1848

二、三报文握手过程抓包

案例工程中,三报文握手在java层面体现在客户端的这一行代码上,创建 Socket 时,会自动连接服务端并完成三次握手;

java 复制代码
Socket socket = new Socket("localhost", 1848); 

服务端阻塞在 accept(),等待连接;一旦返回,说明三次握手完成;

java 复制代码
Socket clientSocket = serverSocket.accept(); 

先启动服务端,再启动客户端:

进入断点,准备建立连接

释放客户端的断点,进入服务端的处理消息的逻辑:

此时三报文握手的过程已经结束了,观察Wireshark

2.1、第一次握手

第一次握手的报文10358 371.405938 127.0.0.1 127.0.0.1 TCP 56 49931 → 1848 [SYN] Seq=0 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM 解释:

字段 含义
10358 报文编号,在这次抓包中的编号
371.405938 抓包开始后的时间戳(秒)
127.0.0.1 → 127.0.0.1 源 IP 和目的 IP(都是 localhost)
TCP 协议类型
56 报文字节数(含 TCP 首部)
49931 → 1848 源端口(49931,客户端临时端口)到目标端口(1848,服务端监听端口)
[SYN] 报文类型标志(发起连接请求)
Seq=0 初始序列号,客户端初始发送序号
Win=65535 窗口大小(接收缓冲区大小)
Len=0 数据长度(SYN 报文本身不带数据)
MSS=65495 最大报文段长度(Maximum Segment Size)是对方发送给我的最大 TCP 有效载荷,协商用
WS=256 窗口扩大因子(Window Scale),用于扩大窗口大小(65535×256)
SACK_PERM 表示支持选择确认(Selective Acknowledgement),提高网络性能

2.2、第二次握手

第二次握手的报文10359 371.405972 127.0.0.1 127.0.0.1 TCP 56 1848 → 49931 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM的解释:

字段 含义
10359 报文编号
371.405972 时间戳
1848 → 49931 服务端端口(1848)回应客户端临时端口(49931)
[SYN, ACK] 服务端回应连接请求,并确认客户端的 SYN 报文
Seq=0 服务端自己的初始序列号为 0
Ack=1 确认号 = 客户端 Seq(0)+ 1,表示收到了客户端的 SYN,对于第一次握手中的seq的确认
Win=65535 服务端窗口大小
Len=0 无负载数据,仅握手信息
MSS=65495 服务端协商的最大段大小
WS=256 服务端窗口扩展因子
SACK_PERM 服务端也支持 SACK

2.3、第三次握手

第三次握手的报文10360 371.405991 127.0.0.1 127.0.0.1 TCP 44 49931 → 1848 [ACK] Seq=1 Ack=1 Win=327424 Len=0的含义:

字段 含义
49931 → 1848 客户端端口 → 服务端端口
[ACK] 确认包,确认服务端的 [SYN, ACK]
Seq=1 客户端的下一个发送序列号(上次 SYN 是 Seq=0,这次是 1)
Ack=1 确认号:表示已收到服务端 Seq=0 的 [SYN] 报文(对于服务端seq的确认)
Win=327424 窗口大小(注意,这里乘了窗口缩放因子)
Len=0 仅为控制报文,无负载数据

针对原理图,理论联系实际,从上面的握手报文可以看出,除了最关键的SYN,ACK,seq,ack以外,;还体现出了对于TCP参数的协商,例如最大段大小,窗口大小,数据长度等。

三、通信过程抓包

在案例工程中,通信过程体现在客户端发送:

java 复制代码
out.write(("Hello Server:" + Thread.currentThread().getName()).getBytes());

服务端接收并回显:

java 复制代码
while ((len = in.read(bytes))!= -1){
    out.write(bytes, 0, len); // echo 回显
    out.flush();
}
报文号 时间戳 源 → 目标 标志位 Seq/Ack Len 说明
44379 1279.762655 49931 → 1848 [PSH, ACK] Seq=1 Ack=1 17 客户端发送"Hello Server..."
44380 1279.762682 1848 → 49931 [ACK] Seq=1 Ack=18 0 服务端确认收到了数据
44469 1283.136551 1848 → 49931 [PSH, ACK] Seq=1 Ack=18 17 服务端回显"Hello Server..."
44470 1283.136566 49931 → 1848 [ACK] Seq=18 Ack=18 0 客户端确认收到了回显

3.1、报文 44379 -- 客户端发数据(PSH, ACK)

49931 → 1848 [PSH, ACK] Seq=1 Ack=1 Len=17

  • 客户端发送数据(17 字节),"Hello Server:main";
  • PSH(Push)表示告诉 TCP 层立即发送,无需等待缓冲区满;
  • Seq=1 是三次握手后起始序列号,这里是重点,因为客户端的第三次握手,报文段没有携带数据,不占用seq,所以这次的seq还是从1开始。
  • Ack=1 表示仍然确认了服务端的 SYN。

3.2、 报文 44380 -- 服务端确认收到数据(ACK)

1848 → 49931 [ACK] Seq=1 Ack=18 Len=0

  • 服务端发送确认 ACK,表示已收到客户端发送的 17 字节(1+17=18);
  • 这是纯 ACK,不带数据。

3.3、报文 44469 -- 服务端回显(PSH, ACK)

1848 → 49931 [PSH, ACK] Seq=1 Ack=18 Len=17

  • 服务端将收到的数据原样回显;
  • PSH 表示回显数据立即发送;
  • Seq=1 是服务端自己的起始序列号;
  • Ack=18 表示还在确认客户端数据;

3.4、报文 44470 -- 客户端确认收到回显(ACK)

49931 → 1848 [ACK] Seq=18 Ack=18 Len=0

  • 客户端收到回显后发出确认 ACK;
  • Seq=18 表示客户端准备下次发送的序号(之前发了 17 字节);
  • Ack=18 表示收到了服务端的 17 字节(1+17=18)。

四、四报文握手过程抓包

案例工程中,四报文挥手在java层面体现在客户端的这一行代码上,通信完成关闭连接时,会通知服务端断开连接,进行四报文挥手的流程;

java 复制代码
socket.close();

执行断点:


三报文握手和四报文挥手,都是客户端发起的

报文号 时间戳 方向 标志位 Len 说明
46892 1380.873591 49931 → 1848 [FIN, ACK] 0 客户端主动断开连接
46893 1380.873609 1848 → 49931 [ACK] 0 服务端确认客户端 FIN
46902 1380.874091 1848 → 49931 [FIN, ACK] 0 服务端也准备断开连接
46903 1380.874114 49931 → 1848 [ACK] 0 客户端确认服务端 FIN,连接彻底关闭

4.1、第一次挥手

第一次挥手报文段46892 1380.873591 127.0.0.1 127.0.0.1 TCP 44 49931 → 1848 [FIN, ACK] Seq=18 Ack=18 Win=327424 Len=0的解释:

字段 含义
46892 报文编号
1380.873591 抓包开始以来的时间戳(秒)
127.0.0.1 → 127.0.0.1 客户端 → 服务端
TCP 协议类型
44 报文长度(含 TCP 头部)
49931 → 1848 客户端临时端口 → 服务端端口
[FIN, ACK] 标志位:客户端请求关闭连接,同时确认服务端数据
Seq=18 序列号,表示上一次客户端发送的数据是以 Seq=17 结尾的(如 "Hello Server" 17 字节),FIN 占用 1
Ack=18 确认号:客户端已收到服务端 Seq=0~17 的数据
Win=327424 客户端窗口大小
Len=0 无数据,仅控制报文

4.2、第二次挥手

第二次挥手报文段46893 1380.873609 127.0.0.1 127.0.0.1 TCP 44 1848 → 49931 [ACK] Seq=18 Ack=19 Win=2161152 Len=0的解释:

字段 含义
46893 报文编号
1380.873609 时间戳
1848 → 49931 服务端端口 → 客户端端口
[ACK] 服务端确认客户端关闭请求
Seq=18 服务端数据已经发到 Seq=17,FIN 尚未发送
Ack=19 确认号:确认客户端 FIN,占用一个序号(Seq=18 → Ack=19)
Win=2161152 服务端窗口大小
Len=0 仅 ACK,没有数据

4.3、第三次挥手

第三次挥手报文段46902 1380.874091 127.0.0.1 127.0.0.1 TCP 44 1848 → 49931 [FIN, ACK] Seq=18 Ack=19 Win=2161152 Len=0的解释:

字段 含义
46902 报文编号
1380.874091 时间戳
1848 → 49931 服务端 → 客户端
[FIN, ACK] 服务端请求关闭,同时 ACK
Seq=18 服务端发出 FIN,占用序号 18(和第二次挥手一致,因为过程中没有发送其他数据)
Ack=19 继续确认客户端的 FIN
Win=2161152 服务端窗口大小
Len=0 无数据,仅控制位

4.4、第四次挥手

第四次挥手报文段46903 1380.874114 127.0.0.1 127.0.0.1 TCP 44 49931 → 1848 [ACK] Seq=19 Ack=19 Win=327424 Len=0的解释:

字段 含义
46903 报文编号
1380.874114 时间戳
49931 → 1848 客户端 → 服务端
[ACK] 客户端确认服务端的关闭
Seq=19 客户端上一次是 Seq=18,FIN 占 1,+1 到 19
Ack=19 表示已经收到服务端的 FIN(Seq=18)
Win=327424 客户端窗口大小
Len=0 无数据

相关推荐
车载测试工程师4 分钟前
车载交换机动态MAC学习和静态MAC绑定&如何获取MAC地址表
网络·tcp/ip·车载系统·wireshark
hjs_deeplearning7 分钟前
认知篇#10:何为分布式与多智能体?二者联系?
人工智能·分布式·深度学习·学习·agent·智能体
静心问道8 小时前
XLSR-Wav2Vec2:用于语音识别的无监督跨语言表示学习
人工智能·学习·语音识别
Cachel wood9 天前
Spark教程6:Spark 底层执行原理详解
大数据·数据库·分布式·计算机网络·spark
忘了ʷºᵇₐ9 天前
Linux系统能ping通ip但无法ping通域名的解决方法
linux·服务器·tcp/ip
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习
zkyqss9 天前
OVS Faucet练习(下)
linux·笔记·openstack
papership10 天前
【入门级-基础知识与编程环境:3、计算机网络与Internet的基本概念】
计算机网络·青少年编程
Jay_51510 天前
C++ STL 模板详解:由浅入深掌握标准模板库
c++·学习·stl
冰茶_10 天前
ASP.NET Core API文档与测试实战指南
后端·学习·http·ui·c#·asp.net