dufaxing To be a better man

PING包数据解析



KYHHbj.png

博客地址

1.前言

PING(Packet Internet Groper)是基于 ICMP(Internet Control Message Protocol,互联网控制报文协议) 的网络诊断工具,用于测试主机之间的连通性、测量往返时间(RTT)及检测丢包。

在不借助抓包工具等情况下,也可通过空口协议栈中数据链路层数据码流分析RRT时延。


2 数据分析

在ICMP协议中,标识符(Identifier)和序列号(Sequence Number)是匹配PING请求(Echo Request)与回复(Echo Reply)的关键字段。

2.1 ICMP Echo请求/回复报文结构

ICMP头部(Echo类型)的格式如下(以IPv4为例):

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Identifier          |        Sequence Number        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Data... (可变长度,PING默认包含时间戳或填充字符)          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Type

    • 8 = Echo Request(请求)

    • 0 = Echo Reply(回复)

  • Code:始终为0

  • Checksum:ICMP报文的校验和。

  • Identifier(标识符):2字节,用于标识会话(通常为进程ID或自定义值)。

  • Sequence Number(序列号):2字节,用于标识同一会话中的不同报文。


2.2 标识符和序列号的作用

(1) Identifier(标识符)

  • 功能:区分不同主机或进程的PING会话。

    • 在Linux/Windows中,PING命令默认将标识符设置为进程ID(例如ping进程的PID)。

    • 同一主机的多个PING进程会使用不同标识符,避免回复混淆。

  • 示例

    • 进程A的PING标识符=0x1234,进程B的PING标识符=0x5678

    • 回复报文必须携带与请求相同的标识符。

(2) Sequence Number(序列号)

  • 功能:标识同一会话中的报文顺序,用于检测丢包或乱序。

    • 每发送一个Echo Request,序列号递增(通常从0开始)。

    • 回复报文必须携带与请求相同的序列号。

  • 示例

    • 第一次PING:序列号=0x0001

    • 第二次PING:序列号=0x0002


2.3 匹配请求与回复的流程

以抓包数据为例(16进制显示ICMP头部):

请求帧(Echo Request)

Type=08, Code=00, Checksum=ABCD  
Identifier=00 01  (0x0001)  
Sequence=00 01    (0x0001)  
Data=...

回复帧(Echo Reply)

Type=00, Code=00, Checksum=1234  
Identifier=00 01  (0x0001)  ← 必须与请求一致  
Sequence=00 01    (0x0001)  ← 必须与请求一致  
Data=...                    ← 数据内容通常原样返回

匹配规则

  1. 回复的IdentifierSequence必须与某个请求完全一致。

  2. 通过这两个字段,可以唯一确定一个请求的回复,即使网络中同时存在多个PING会话。


2.4 总结

  • 标识符:区分不同PING会话(如多进程场景)。

  • 序列号:标识同一会话中的报文顺序。

  • 匹配关键:通过Identifier + Sequence唯一关联请求与回复,确保RTT计算的准确性。

RRT = 相同标识符与序列号下,回复报文接受时间-请求报文发送时间

3 举例

完整的 Ping 请求(Echo Request)和回复(Echo Reply)的数据链路层(Ethernet + IP + ICMP)数据包示例,包含 RTT(Round-Trip Time)时延计算 的详细解析。假设通信双方如下:

  • 主机A(发送请求)

    • MAC: 00:11:22:33:44:55

    • IP: 192.168.1.100

  • 主机B(回复)

    • MAC: AA:BB:CC:DD:EE:FF

    • IP: 8.8.8.8

3.1 Ping 请求(Echo Request)

完整数据包(Hex 格式)

FFFFFFFFFFFF 001122334455 0800 4500005400004000FF01 0000 C0A80164 08080808 0800 F5CA 0001 0001 6162636465666768696A6B6C6D6E6F70

关键字段解析:

字段 说明
Ethernet 目标 MAC FFFFFFFFFFFF 广播地址(实际场景中为网关或目标 MAC)。
Ethernet 源 MAC 001122334455 主机A的 MAC。
IP 协议 0800 IPv4。
IP 源地址 C0A80164 192.168.1.100。
IP 目标地址 08080808 8.8.8.8。
ICMP 类型 08 Echo Request。
ICMP 标识符 0001 用于匹配请求与回复(通常为进程 ID)。
ICMP 序列号 0001 请求序号。
数据部分 616263…6F70 ASCII 数据 “abcdefghijklmnop”。

3.2 Ping 回复(Echo Reply)

完整数据包(Hex 格式)

001122334455 AABBCCDDEEFF 0800 4500005400004000FF01 0000 08080808 C0A80164 0000 FDCA 0001 0001 6162636465666768696A6B6C6D6E6F70

关键字段解析:

字段 说明
Ethernet 目标 MAC 001122334455 主机A的 MAC。
Ethernet 源 MAC AABBCCDDEEFF 主机B的 MAC。
IP 协议 0800 IPv4。
IP 源地址 08080808 8.8.8.8。
IP 目标地址 C0A80164 192.168.1.100。
ICMP 类型 00 Echo Reply。
ICMP 标识符 0001 与请求包一致。
ICMP 序列号 0001 与请求包一致。
数据部分 616263…6F70 原样返回请求的数据。

3.3 RTT(Round-Trip Time)时延计算

RTT 是 从发送 Echo Request 到接收 Echo Reply 的时间差,通常由 ping 工具自动计算。以下是手动计算方法:

(1)抓包工具记录时间戳

  • Wireshark 会显示每个包的时间戳(如 Frame 1Frame 2 的时间差)。

  • tcpdump 输出示例:

12:00:00.000000 IP 192.168.1.100 > 8.8.8.8: ICMP echo request, id 1, seq 1, length 64
12:00:00.002400 IP 8.8.8.8 > 192.168.1.100: ICMP echo reply, id 1, seq 1, length 64

(2)手动计算(需高精度时间戳)

如果通过代码抓包(如 Python 的 scapy),可记录发送和接收时间:

from scapy.all import *
import time

# 发送 Echo Request
send_time = time.time()
send(IP(dst="8.8.8.8")/ICMP(type=8, id=1, seq=1)/"abcdefghijklmnop")

# 捕获 Echo Reply
def callback(pkt):
    if pkt[ICMP].type == 0 and pkt[ICMP].id == 1 and pkt[ICMP].seq == 1:
        recv_time = time.time()
        rtt = (recv_time - send_time) * 1000  # 转为毫秒
        print(f"RTT: {rtt:.2f} ms")

sniff(filter="icmp and host 8.8.8.8", prn=callback, timeout=1)

输出示例:

RTT: 2.41 ms

上一篇 PDCP加解密DEMO

Comments

Content