3、DoIP协议栈架构:分层模型、实体关系与消息类型

好,咱们进入正题。DoIP协议栈,说白了就是一套让诊断数据在以太网上跑起来的规矩。我刚开始接触的时候,也觉得这东西挺复杂,但拆开来看,其实就三层:传输层、网络层、应用层。嗯,咱们一层一层说。

3.1 DoIP协议栈分层模型

DoIP协议栈,它并不是从零造轮子。它建立在标准的TCP/IP协议栈之上。我个人习惯把它看成四层,但核心的DoIP逻辑集中在三层:

OSI层 DoIP协议栈对应 典型协议/功能
应用层 DoIP应用层 诊断消息(UDS)、车辆发现、路由激活
传输层 TCP / UDP TCP用于可靠诊断,UDP用于发现和广播
网络层 IPv4 / IPv6 IP地址分配、路由
数据链路层 以太网MAC 100BASE-TX / 1000BASE-T / BroadR-Reach

你想想看,为什么诊断要用TCP?因为诊断数据不能丢。我在项目中遇到过,有一次用UDP发诊断请求,结果丢了一个报文,ECU没响应,诊断仪直接报超时。排查了半天,最后发现是网络拥塞导致的。所以,DoIP的诊断消息强制走TCP,而车辆发现和状态通告这类广播消息,才用UDP。

核心要点:DoIP协议栈不是新协议,它是UDS over TCP/IP的一种封装。说白了,就是把传统的CAN诊断报文,打包成以太网帧来传输。

3.2 DoIP实体与诊断仪的关系

这里有个概念很重要——DoIP实体。它不是一个物理设备,而是一个逻辑节点。每个支持DoIP的ECU内部,都有一个DoIP实体。诊断仪本身也是一个DoIP实体。

它们之间的关系,我总结为三个角色:

  • 诊断仪(Tester):主动发起连接,发送诊断请求。它就像一个问问题的人。
  • DoIP网关(Gateway):通常位于中央网关中,负责路由诊断消息到目标ECU。它像一个交通指挥员。
  • 目标ECU(Target ECU):实际执行诊断功能的节点。它负责回答问题。

我记得有一次调试,诊断仪死活连不上某个ECU。查了半天,发现是DoIP网关的路由表没配好。嗯,这里要注意:DoIP实体之间通过逻辑地址来识别,而不是物理地址。每个ECU都有一个16位的逻辑地址,诊断仪也有自己的逻辑地址。

避坑指南:我曾经遇到过一个问题——诊断仪发送了路由激活请求,但ECU就是不响应。后来发现,是ECU的DoIP实体没有正确配置“激活线”状态。DoIP实体在收到路由激活前,是不会处理诊断消息的。这个顺序千万别搞反。

3.3 DoIP消息类型概览

DoIP的消息类型,说白了就两大类:控制类消息诊断类消息。控制类消息负责建立连接、管理会话;诊断类消息才是真正干活的。

我整理了一个表格,把常用的消息类型列出来:

消息类型 名称 用途 传输层
0x0001 Generic DoIP header negative acknowledge 通用否定应答,告诉对方“你发的消息我不认识” TCP/UDP
0x0002 Vehicle Identification Request 车辆识别请求,诊断仪用来发现车辆 UDP
0x0003 Vehicle Identification Response 车辆识别响应,ECU告诉诊断仪“我在这里” UDP
0x0004 Routing Activation Request 路由激活请求,诊断仪申请与ECU建立诊断通道 TCP
0x0005 Routing Activation Response 路由激活响应,ECU同意或拒绝连接 TCP
0x0006 Alive Check Request 心跳检测,确认对方还活着 UDP
0x0007 Alive Check Response 心跳应答 UDP
0x8001 Diagnostic Message 真正的诊断请求/响应(UDS消息) TCP

你可能会问,为什么要有这么多控制消息?我举个例子:车辆识别请求。诊断仪插上OBD接口后,它不知道这辆车是什么品牌、什么型号。它先发一个UDP广播,问“谁在?”。所有支持DoIP的ECU都会回复。诊断仪拿到回复后,才知道该跟谁建立TCP连接。

注意:诊断消息(0x8001)只能走TCP。为什么?因为诊断数据不能丢。你想想看,如果ECU执行了一个“写入配置”的请求,结果响应丢了,诊断仪以为没成功,又发了一次,那ECU就执行了两次。后果可能很严重。

嗯,消息类型这块,我建议你重点记住两个:路由激活(0x0004/0x0005)诊断消息(0x8001)。这两个是实际开发中最常用的。其他的,比如Alive Check,说白了就是心跳包,用来检测连接是否还活着。我在项目中就遇到过,诊断仪和ECU之间的TCP连接因为长时间空闲被路由器断开了,结果Alive Check没通过,诊断会话自动关闭。后来我们加了一个定时发送Alive Check的机制,问题就解决了。

好了,这一章的内容就这些。下一章咱们聊聊DoIP的报文格式,看看每个字节到底是怎么定义的。到时候我会拿一个实际的抓包数据来拆解,保证你看完就能上手。