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=... ← 数据内容通常原样返回
匹配规则:
-
回复的
Identifier
和Sequence
必须与某个请求完全一致。 -
通过这两个字段,可以唯一确定一个请求的回复,即使网络中同时存在多个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 1
和Frame 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