3、DoIP消息格式:通用DoIP消息头结构、Payload类型与编码、消息类型分类

好,咱们进入DoIP协议最核心的部分——消息格式。说实话,我刚接触DoIP那会儿,看着那一串十六进制字节,脑袋也是嗡嗡的。但后来我发现,只要把消息头结构吃透了,后面Payload怎么编解码、消息怎么分类,其实都是顺理成章的事。

这一节,我会带着大家把DoIP消息的「骨架」拆开来看。你想想看,一辆车和诊断仪之间要说话,总得有个统一的信封吧?这个信封就是通用消息头。咱们先看信封长什么样,再聊里面装了什么内容。

3.1 通用DoIP消息头结构

DoIP消息头是固定的8字节。嗯,这里要注意,不管后面Payload有多长,这8个字节雷打不动。我个人习惯把这8个字节分成四个字段来记:

字节偏移 字段名称 长度 说明
0 协议版本 1字节 当前固定为0x02(ISO 13400-2:2012)
1 反向协议版本 1字节 取协议版本的按位取反,即0xFD
2-3 Payload类型 2字节 标识消息的具体用途
4-7 Payload长度 4字节 后续Payload的字节数(大端序)

关键点:反向协议版本字段是用来做快速校验的。接收方收到消息后,把协议版本和反向协议版本相加,如果结果不是0xFF,说明消息头损坏了,直接丢弃。我在项目中遇到过好几次因为网络干扰导致版本字段出错的情况,这个机制确实能快速过滤掉垃圾数据。

举个例子,一个完整的DoIP消息头在抓包工具里看起来是这样的:

02 FD 00 01 00 00 00 04

拆开来看:

  • 02 — 协议版本,ISO 13400-2:2012
  • FD — 反向协议版本,0x02取反得0xFD
  • 00 01 — Payload类型,0x0001代表车辆识别请求
  • 00 00 00 04 — Payload长度,4字节

说白了,这8个字节就是DoIP通信的「身份证」。任何不符合这个结构的报文,接收方都会直接无视。

3.2 Payload类型与编码

消息头之后跟着的就是Payload。Payload怎么编码?这得看Payload类型字段的值。ISO 13400-2标准里定义了一大堆类型,我挑几个最常用的给大家讲讲。

Payload的编码方式其实不复杂,主要分两类:

  • 固定长度Payload:比如车辆识别请求(0x0001),Payload就是4字节的逻辑地址。编码时直接按大端序填进去就行。
  • 可变长度Payload:比如诊断消息(0x8001),Payload里包含目标地址、源地址和实际的UDS诊断数据。这种就需要在Payload内部再嵌套一个子结构。

我记得有一次调试,发现诊断仪发出去的DoIP消息,ECU就是不响应。抓包一看,Payload长度字段填错了,多填了2个字节。ECU等着收完数据,结果一直收不到,直接超时了。所以啊,Payload长度这个字段,一定要算准。

小技巧:写代码的时候,我习惯在填充Payload长度之前,先把整个消息组装好,然后回头再填长度。这样不容易算错。你想想看,如果先填了长度再拼Payload,万一中间改了数据,长度还得重新算,多麻烦。

咱们看一个诊断消息的Payload编码示例:

// 诊断消息Payload结构(类型0x8001)
// 字节0-1: 目标逻辑地址 (2字节)
// 字节2-3: 源逻辑地址 (2字节)
// 字节4-n: UDS诊断数据

// 示例:发送诊断请求 10 03(诊断会话控制-扩展会话)
// 目标地址: 0x0E00 (ECU逻辑地址)
// 源地址: 0x0E80 (诊断仪逻辑地址)
// UDS数据: 10 03

Payload (共8字节):
0E 00 0E 80 10 03

3.3 消息类型分类

DoIP的消息类型,按功能可以分成四大类。我习惯用「查、连、控、诊」四个字来记:

分类 Payload类型范围 典型消息 用途
车辆发现 0x0001 - 0x0004 车辆识别请求/响应 诊断仪发现网络中的车辆
连接管理 0x0005 - 0x0008 路由激活请求/响应 建立诊断会话连接
数据控制 0x8001 - 0x8004 诊断消息、诊断ACK 传输实际的UDS诊断数据
事件通知 0x4001 - 0x4003 车辆状态变化通知 ECU主动上报状态变化

这里我要特别强调一下「连接管理」类中的路由激活消息。为什么?因为这是DoIP安全机制的入口。我曾经在项目里见过有人把路由激活的Payload类型填错了,结果ECU一直不响应,折腾了两天才发现是类型字段写成了0x0006而不是0x0005。

避坑指南:路由激活请求(0x0005)的Payload里包含一个「激活类型」字段。常见的激活类型有0x01(默认激活)和0x02(安全激活)。如果你用的是安全激活,记得在Payload里带上认证数据,否则ECU会直接拒绝。我曾经因为忘了带认证数据,被ECU连续拒绝了5次,触发了ECU的防攻击机制,锁了10分钟……

再说说「事件通知」类。这类消息比较特殊,它不是诊断仪发起的,而是ECU主动上报的。比如车辆熄火、网络断开等场景,ECU会发一个0x4003(车辆状态变化通知)给诊断仪。嗯,这里要注意,诊断仪收到这类消息后,通常需要回复一个确认,否则ECU会认为诊断仪没收到,继续重发。

最后总结一下:

  • 消息头8字节,固定结构,反向协议版本用来做快速校验
  • Payload编码分固定长度和可变长度两种,长度字段一定要算准
  • 消息类型分四大类,路由激活是安全机制的关键入口

下一节我们会深入路由激活的具体流程,以及如何通过DoIP实现安全认证。到时候我会分享一个我在实际项目中遇到的「路由激活失败」的经典案例,保证让你印象深刻。