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位的无符号整数,取值范围从 0x00000xFFFF

常见的类型我列个表,你一看就明白:

负载类型值 含义 说明
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:2012
  • FD:逆向协议版本,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个字段看一遍,很多问题一眼就能发现。