4、DoIP报文格式:通用报文头结构、诊断报文(0x8001)、诊断确认报文(0x8002)、Alive Check报文(0x8003)
好,咱们今天聊聊DoIP的报文格式。说实话,这部分内容在项目里是绕不开的。你想想看,不管你是做诊断仪还是ECU,报文格式搞错了,通信直接就断了。我刚开始接触DoIP时,也在这上面栽过跟头。
4.1 通用报文头结构
每个DoIP报文,都带一个固定的头部。这个头部长啥样?一共8个字节,结构非常清晰。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 协议版本 | 1 | 当前固定为0x02(ISO 13400-2:2012) |
| 反向协议版本 | 1 | 取反,用于快速校验 |
| 负载类型 | 2 | 标识报文用途,如0x8001、0x8002等 |
| 负载长度 | 4 | 后续数据的字节数 |
我个人习惯,在解析报文时,先检查协议版本和反向协议版本。如果两者之和不是0xFF,那这个报文基本可以扔掉了。嗯,这里要注意,负载长度是4字节无符号整数,最大支持4GB的数据。但在实际项目中,诊断报文很少超过几KB。
核心要点:通用报文头是所有DoIP报文的基础。解析任何报文前,必须先验证头部合法性。
4.2 诊断报文(0x8001)
诊断报文,说白了就是UDS诊断请求和响应的载体。负载类型是0x8001。它的结构在通用头部之后,还有额外的字段。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 源地址 | 2 | 发送方逻辑地址 |
| 目标地址 | 2 | 接收方逻辑地址 |
| 用户数据 | 可变 | UDS诊断数据(如0x10 0x03等) |
我在项目中遇到过一个问题:源地址和目标地址填反了。结果ECU收到报文后,直接丢弃了。你想想看,诊断仪发请求,源地址应该是诊断仪自己的地址,目标地址是ECU的地址。这个顺序千万别搞错。
避坑指南:我曾经在调试时,发现诊断仪发出去的请求,ECU就是不响应。查了半天,原来是源地址写成了0x0000。记住,逻辑地址0x0000是无效地址,不能用于通信。
4.3 诊断确认报文(0x8002)
诊断确认报文,是DoIP协议层对诊断报文的确认。它不代表UDS诊断成功,只代表DoIP层收到了报文。负载类型是0x8002。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 源地址 | 2 | ECU的逻辑地址 |
| 目标地址 | 2 | 诊断仪的逻辑地址 |
| 确认码 | 1 | 0x00表示成功,其他值表示错误 |
| 预留 | 3 | 填充0x00 |
确认码的值,我列一下常见的:
- 0x00:确认成功,ECU已接收诊断报文
- 0x01:源地址无效
- 0x02:目标地址无效
- 0x03:诊断报文格式错误
- 0x04:未知错误
为什么会需要这个确认报文?因为UDS诊断是应用层协议,DoIP是传输层协议。ECU收到DoIP报文后,先确认报文格式正确,再交给UDS处理。如果格式不对,直接回复确认码错误,诊断仪就知道重发了。
注意:诊断确认报文不是UDS诊断响应。UDS诊断响应是0x8001报文中的用户数据。别把这两个搞混了。我见过有人把确认码当成诊断结果,结果闹了笑话。
4.4 Alive Check报文(0x8003)
Alive Check报文,也叫心跳报文。它的作用是让ECU告诉诊断仪:我还活着。负载类型是0x8003。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 源地址 | 2 | ECU的逻辑地址 |
| 目标地址 | 2 | 通常为0x0000(广播) |
Alive Check报文没有用户数据,只有源地址和目标地址。ECU会定期发送这个报文,比如每3秒一次。诊断仪收到后,就知道这个ECU还在网络上。
我记得有一次,客户反馈说诊断仪连不上ECU。我抓包一看,ECU根本没发Alive Check报文。后来发现是ECU的网络栈初始化有问题,导致心跳没启动。嗯,这个坑踩得值。
关键点:Alive Check报文是DoIP网络管理的一部分。它帮助诊断仪动态发现ECU,也用于检测ECU是否离线。如果诊断仪连续几次没收到心跳,就可以认为ECU已断开。
4.5 报文格式对比
我把这三种报文的区别,整理成了一张表。方便你快速查阅。
| 报文类型 | 负载类型 | 主要用途 | 是否有用户数据 |
|---|---|---|---|
| 诊断报文 | 0x8001 | 传输UDS诊断请求/响应 | 是 |
| 诊断确认报文 | 0x8002 | 确认DoIP层收到诊断报文 | 否(只有确认码) |
| Alive Check报文 | 0x8003 | ECU心跳,表明在线状态 | 否 |
说白了,这三种报文各司其职。诊断报文负责干活,诊断确认报文负责说“收到了”,Alive Check报文负责说“我还在”。你想想看,如果没有这些分工,网络通信会乱成什么样。
个人建议:在开发DoIP协议栈时,先把报文解析器写好。我习惯用状态机来处理,先解析通用头部,再根据负载类型分发到不同的处理函数。这样代码结构清晰,也容易调试。
好了,这一章的内容就到这里。报文格式是DoIP的基础,一定要熟练掌握。下一章,咱们聊聊DoIP的连接建立和路由激活,那才是真正开始通信的关键步骤。