4、DoIP报文通用结构:协议版本、逆向协议版本、负载类型、负载长度、负载数据
好,咱们今天来聊聊DoIP报文最基础的结构。说白了,就是一辆车和诊断仪之间,到底是怎么“说话”的。你想想看,如果两个人要聊天,总得有个约定好的格式吧?比如先打招呼,再说正事。DoIP报文也一样,它有一套固定的“骨架”。
我个人习惯,把DoIP报文看成是一个“信封”。信封外面写着版本号、类型,信封里面才是真正要传递的诊断数据。这个比喻,我用了好多年,挺管用的。
4.1 协议版本与逆向协议版本
先看报文头的前两个字节:协议版本和逆向协议版本。
协议版本(Protocol Version),目前主流的就是 0x02。这个值代表ISO 13400-2:2012版本。我记得早期有些设备用的是 0x01,现在已经很少见了。如果你抓包看到 0xFF,那通常是用于特殊测试,别大惊小怪。
逆向协议版本(Inverse Protocol Version),这个设计很有意思。它就是协议版本的按位取反。比如版本是 0x02,逆向版本就是 0xFD(0xFF - 0x02)。
为什么要搞个逆向版本?
说白了,就是为了快速校验。接收方只要把这两个字节相加,如果结果不是 0xFF,那这个报文肯定有问题,直接扔掉。我曾经在项目里遇到过,某个供应商的网关芯片有bug,逆向版本算错了,结果导致诊断仪死活连不上车。排查了整整两天,最后发现是这么个小问题。
我的小技巧:写代码解析时,别偷懒只检查协议版本。顺手把逆向版本也校验一下,能帮你过滤掉很多异常报文。
4.2 负载类型
接下来两个字节,是负载类型(Payload Type)。这个字段决定了报文要干什么。它是个16位的无符号整数,取值范围从 0x0000 到 0xFFFF。
常见的类型我列个表,你一看就明白:
| 负载类型值 | 含义 | 说明 |
|---|---|---|
| 0x0001 | 车辆声明 | 车辆上线时广播自己的存在 |
| 0x0002 | 车辆识别请求 | 诊断仪问:“你是谁?” |
| 0x0003 | 车辆识别响应 | 车辆回答:“我是XX车型” |
| 0x0004 | 路由激活请求 | 诊断仪说:“我要开始干活了” |
| 0x0005 | 路由激活响应 | 车辆说:“好的,通道已开” |
| 0x8001 | 诊断消息 | 真正的UDS诊断数据 |
嗯,这里要注意。负载类型 0x8001 是咱们最常用的,因为它承载了真正的诊断请求和响应。其他类型大多是握手和建立连接用的。
4.3 负载长度
负载长度(Payload Length)占4个字节。它告诉接收方:后面跟着的数据到底有多长。单位是字节,范围从0到4294967295(2^32 - 1)。
你可能会问:“为什么需要这个字段?” 因为DoIP底层用的是TCP或UDP,这两种协议都是流式传输。如果没有长度字段,接收方就不知道什么时候该停止读取。我曾经见过一个新手写的代码,没检查负载长度,直接读了整个TCP缓冲区,结果把下一个报文也吞进来了,导致解析全乱套。
避坑指南:我曾经在解析时,发现负载长度和实际数据对不上。后来查出来,是发送方在填充长度时用了小端序,而我的解析器默认是大端序。记住,DoIP报文头里的多字节字段,一律是网络字节序(大端序)。
4.4 负载数据
最后就是负载数据(Payload Data)了。它的内容完全由前面的负载类型决定。比如:
- 如果负载类型是
0x8001,负载数据就是一条完整的UDS消息。 - 如果负载类型是
0x0004,负载数据就是路由激活请求的参数。
负载数据的长度,必须和负载长度字段的值一致。多一个字节、少一个字节,都会导致解析失败。
4.5 完整的报文结构示例
说了这么多,不如直接看个例子。下面是一个完整的DoIP诊断请求报文:
02 FD 80 01 00 00 00 08 10 03 00 00 00 00 00 00
咱们来拆解一下:
02:协议版本,表示ISO 13400-2:2012FD:逆向协议版本,0x02的取反80 01:负载类型,0x8001,表示诊断消息00 00 00 08:负载长度,8个字节10 03 00 00 00 00 00 00:负载数据,这是一条UDS诊断会话控制请求(0x10 0x03)
我的习惯:写解析代码时,我会先定义一个结构体,把报文头映射进去。这样代码清晰,也容易维护。比如用C语言,可以这样定义:
typedef struct {
uint8_t protocol_version;
uint8_t inverse_version;
uint16_t payload_type;
uint32_t payload_length;
uint8_t payload_data[];
} DoIPHeader;
好了,这就是DoIP报文最核心的通用结构。说白了,就是“版本 + 类型 + 长度 + 数据”这么简单。但越是简单的东西,越容易在细节上出错。下次你抓包分析时,不妨先盯着这5个字段看一遍,很多问题一眼就能发现。