第4章:DoIP报文结构——通用头部格式与常见报文类型

好,咱们进入正题。DoIP报文长什么样?说白了,它就是在标准TCP/IP数据包里面,又套了一层自己的“信封”。这个信封就是通用报文头部。我当年第一次看协议文档时,觉得这东西挺啰嗦,后来调试多了才发现——每个字节都有它的脾气。

4.1 通用DoIP报文头部格式

所有DoIP报文,不管你是诊断请求还是路由激活,都必须带上这个8字节的头部。结构非常固定,我直接给你拆开看:

字节偏移 字段名 长度 说明
0 协议版本号 1字节 当前标准值为0x02(ISO 13400-2:2012)
1 反向协议版本号 1字节 必须等于0x02,用于版本校验
2-3 负载类型码 2字节 标识报文的具体用途(见下文)
4-7 负载长度 4字节 后续数据的字节数(不含头部)

嗯,这里要注意:反向协议版本号这个字段,我见过不少新手踩坑。它必须和协议版本号一致,否则接收方直接丢弃报文。为什么这么设计?其实就是个简单的握手校验,防止版本不匹配的节点乱入。

核心要点:DoIP头部总共8字节,前2字节是版本校验,中间2字节告诉对方“我要干什么”,最后4字节告诉对方“我带了多长的数据”。

4.2 负载类型码详解

类型码是2字节的整型值,范围从0x0000到0xFFFF。ISO 13400-2里定义了几十种,但实际项目中常用的也就那么十几种。我按功能分组给你列出来:

4.2.1 节点管理类

  • 0x0001 —— 通用DoIP头部否定确认。说白了就是“你发的东西我不认”,后面会带一个否定码告诉你为啥不认。
  • 0x0002 —— 车辆识别请求。诊断仪发这个,ECU就得报上自己的VIN、EID、GID等信息。
  • 0x0004 —— 车辆识别响应。ECU回复的车辆信息。
  • 0x0005 —— 路由激活请求。这是建立诊断通道的关键一步,我后面会专门讲。
  • 0x0006 —— 路由激活响应。ECU告诉你“通道已开”或者“拒绝接入”。

4.2.2 诊断通信类

  • 0x8001 —— 诊断消息(UDS over DoIP)。这是最常用的类型,诊断仪发UDS请求就用这个。
  • 0x8002 —— 诊断消息确认。ECU收到诊断请求后,先回一个确认包,再回真正的诊断响应。
  • 0x8003 —— 诊断消息否定确认。ECU告诉你“诊断消息格式不对”或者“通道没激活”。

4.2.3 连接管理类

  • 0x0007 —— 保活请求。诊断仪定期发这个,告诉ECU“我还活着,别关通道”。
  • 0x0008 —— 保活响应。ECU回复确认。
  • 0x4001 —— 告警事件通知。ECU主动上报一些异常状态,比如电压不稳、温度过高等。

个人经验:我建议你在做DoIP协议栈时,先把0x0001(否定确认)和0x8003(诊断否定确认)这两个类型码的解析逻辑写好。因为调试阶段,90%的报文都是这两个——不是这里错就是那里错。

4.3 负载长度字段的坑

负载长度是4字节,大端序。这个字段我吃过亏。有一次我在项目里发现,诊断仪发过来的报文长度总是对不上,后来抓包一看——负载长度字段写的是0x00000100,但实际后面只跟了200字节数据。ECU按照256字节去解析,直接读到脏数据。

为什么会这样?因为有些开发者在计算长度时,把头部也算进去了。记住:负载长度只包含头部之后的数据,头部本身不算。

避坑指南:我曾经在测试中遇到一个ECU,它收到路由激活请求后,回复的负载长度字段写的是0x00000000,但后面明明跟了4字节的响应数据。结果诊断仪一直收不到有效响应,超时断开连接。后来发现是协议栈里长度计算逻辑写错了——把“无负载”和“负载长度为0”搞混了。

4.4 常见报文类型概览

我把项目中最高频的几种报文类型整理成了一张速查表,你调试时可以直接对照:

类型码 报文名称 方向 典型场景
0x0002 车辆识别请求 诊断仪 → ECU 刚建立TCP连接时,诊断仪先问“你是谁”
0x0004 车辆识别响应 ECU → 诊断仪 ECU回复VIN、EID等信息
0x0005 路由激活请求 诊断仪 → ECU 识别完成后,申请打开诊断通道
0x0006 路由激活响应 ECU → 诊断仪 ECU同意或拒绝激活
0x8001 诊断消息 双向 真正的UDS诊断请求/响应
0x0007 保活请求 诊断仪 → ECU 每隔几秒发一次,防止通道超时

你想想看,整个DoIP通信流程,其实就是这几个报文来回倒腾。先识别,再激活,然后发诊断,最后保活。搞懂了这六种报文,DoIP通信你就掌握了七七八八。

4.5 一个完整的报文示例

光说不练假把式。我给你看一个真实的诊断请求报文,抓包抓到的:

02 02 80 01 00 00 00 05 10 03 00 00 00 00
|--头部--| |--类型--| |----长度----| |--UDS数据--|

拆开来看:

  • 02 02 —— 协议版本0x02,反向版本0x02,校验通过。
  • 80 01 —— 类型码0x8001,表示这是一个诊断消息。
  • 00 00 00 05 —— 负载长度5字节。
  • 10 03 00 00 00 00 —— 后面5字节是UDS数据(这里是一个诊断会话控制请求,0x10 0x03)。

注意看,负载长度写的是5,但UDS数据实际占了5字节。完全吻合。如果这里长度写错了,ECU就会解析出问题。

总结一下:DoIP报文头部就是8字节的“身份证”,类型码告诉对方“我要干啥”,负载长度告诉对方“我带了多重的行李”。搞懂这个,你就能看懂所有DoIP报文了。

下一章我会讲路由激活的完整流程,包括激活请求里那些逻辑地址、激活类型到底怎么填。到时候咱们再细聊。