以太网帧解包原理及socket中解包格式字符确定方法
以太网帧解包原理与格式字符的确定逻辑
刚好做过socket抓包相关的开发,来给你掰扯清楚这个问题——先从以太网帧的基础结构说起,再对应到你用的struct.unpack格式字符上。
一、先搞懂以太网II帧的核心头部结构
我们平时用的绝大多数以太网帧都是以太网II帧,它的头部固定是14字节,从前往后依次是三个核心字段:
- 目的MAC地址:6字节(48位),用来标识接收方的网络接口(比如广播地址就是
ff:ff:ff:ff:ff:ff) - 源MAC地址:6字节(48位),发送方的网络接口物理地址
- 以太网类型字段:2字节(16位),用来标识上层协议类型(比如
0x0800对应IPv4,0x0806对应ARP)
二、拆解你用的格式字符串:! 6s 6s H
现在逐个解析每个部分的作用,完全对应上面的帧结构:
!:这是字节序标记,代表网络字节序(大端序)。因为所有网络协议的多字节字段(比如这里的类型字段)都是用大端序传输的,而本地机器可能是小端序(比如x86架构的电脑),所以必须用!指定解包时按大端序解析,否则会得到错误的数值。6s:s表示解析为字节串类型,前面的6表示取6个字节。第一个6s对应目的MAC地址,第二个6s对应源MAC地址——MAC地址刚好是6字节,用字节串保存最直接,之后你可以自己把它转换成XX:XX:XX:XX:XX:XX的可读格式。H:H代表无符号短整型(占2字节),正好匹配以太网类型字段的2字节长度。解包后会得到一个整数,比如2048就是0x0800,对应IPv4协议,完全符合预期。
三、为什么截取data[0:14]?
因为以太网II帧的头部刚好是14字节,截取前14字节就能精准拿到这三个核心字段,剩下的部分就是上层协议的负载(比如IPv4数据包、ARP报文等)。
举个实际的例子,假设你抓包得到的前14字节是:
b'\xff\xff\xff\xff\xff\xff\x00\x11\x22\x33\x44\x55\x08\x00'
用这个格式解包后会得到:
(b'\xff\xff\xff\xff\xff\xff', b'\x00\x11\x22\x33\x44\x55', 2048)
其中2048就是0x0800,对应IPv4协议,完美匹配预期。
四、通用的格式字符确定方法
核心思路就是严格对齐帧结构的每个字段的长度和类型:
- 第一步:查清楚你要解析的帧类型(比如以太网II、802.3)的官方结构定义,明确每个字段的字节数和数据类型
- 第二步:对应
struct模块的格式符:- 固定长度的字节序列:用
Ns(N是字节数,比如MAC地址用6s) - 整数类型:根据字节数选对应格式符(1字节用
B,2字节用H,4字节用I等)
- 固定长度的字节序列:用
- 第三步:必须加上字节序标记
!,因为网络协议几乎都是大端序传输的,避免本地字节序干扰
内容的提问来源于stack exchange,提问作者Alpha Centorus
相关产品推荐
相关产品推荐

