2、网络架构基础:TCP/IP协议栈回顾、UDP与TCP在DoIP中的应用场景、以太网帧结构、IP地址与端口分配
好,咱们正式开始第二讲。在动手写DoIP协议栈之前,有一件事必须做——把网络基础打牢。你想想看,DoIP说白了就是把传统的诊断数据包,塞进以太网帧里,通过IP网络传输。如果TCP/IP协议栈的基本原理都不清楚,后面调试起来会非常痛苦。
我个人习惯是,每接触一个新协议,先花半天时间把底层网络模型过一遍。不是为了背概念,而是为了知道「数据到底是怎么从诊断仪跑到ECU里去的」。今天我们就来聊聊这个话题。
2.1 TCP/IP协议栈回顾
先看这张经典的协议栈分层图。DoIP工作在应用层,但它依赖下面四层的协同工作。
| 层级 | 典型协议 | 在DoIP中的角色 |
|---|---|---|
| 应用层 | DoIP、UDS | 封装诊断请求/响应 |
| 传输层 | TCP、UDP | 提供可靠或不可靠传输 |
| 网络层 | IP | 路由寻址,决定数据包去哪 |
| 链路层 | 以太网 | 物理帧封装,MAC地址通信 |
嗯,这里要注意:DoIP并不是直接操作网卡的。它调用的是Socket API。操作系统内核帮你完成了TCP分段、IP路由、以太网封装这些脏活累活。我们写代码时,只需要关心应用层的报文格式和Socket选项。
2.2 UDP与TCP在DoIP中的应用场景
为什么DoIP同时需要UDP和TCP?说白了,两种场景需求不同。
2.2.1 UDP:用于发现与广播
UDP是无连接的,发出去就不管了。在DoIP里,它主要干两件事:
- 车辆发现:诊断仪发送广播,问「谁在?」,ECU用UDP回复「我在,这是我的IP」。
- 车辆信息通告:ECU启动时主动广播自己的DoIP能力。
我记得第一次调试车辆发现功能时,UDP广播包死活收不到。查了半天,发现是Windows防火墙把广播端口13400给拦了。嗯,这种问题在开发板上很少见,但在PC端做模拟测试时特别容易中招。
2.2.2 TCP:用于诊断数据交换
诊断请求和响应必须可靠。TCP提供了确认重传、流量控制、保序机制。DoIP规定:
- 每个ECU最多支持2个TCP连接。
- 诊断数据必须通过TCP发送。
- 连接建立后,先做DoIP路由激活,才能发UDS报文。
你想想看,如果诊断数据用UDP传,万一丢了一个字节,ECU可能解析出错误的诊断指令,后果很严重。所以ISO 13400标准强制要求诊断数据走TCP。
2.3 以太网帧结构
虽然我们写代码时很少直接操作以太网帧头,但理解它有助于排查底层问题。一个标准的以太网帧长这样:
| 前导码(7B) | 定界符(1B) | 目的MAC(6B) | 源MAC(6B) | 类型(2B) | 数据(46-1500B) | FCS(4B) |
DoIP数据包就藏在「数据」字段里。类型字段如果是0x0800,表示上层是IP协议。如果是0x0806,那是ARP。
我在调试一个百兆以太网的DoIP项目时,发现诊断响应偶尔超时。用抓包工具一看,好家伙,以太网帧的FCS校验错误率高达3%。原来是PCB布线时,差分信号线没等长,导致信号质量差。嗯,硬件问题有时候比软件问题更难查。
2.4 IP地址与端口分配
DoIP使用固定的端口号,这是ISO 13400规定的,不能随便改。
| 端口 | 协议 | 用途 |
|---|---|---|
| 13400 | UDP | 车辆发现、车辆信息通告 |
| 13400 | TCP | 诊断数据交换、路由激活 |
IP地址方面,DoIP支持两种模式:
- 静态IP:适用于生产线或实验室环境,手动配置。
- 动态IP(DHCP):适用于售后诊断,ECU启动时自动获取IP。
我个人习惯在开发阶段用静态IP,比如192.168.0.100,避免DHCP服务器没搭好导致连不上。等协议栈稳定了,再切到DHCP模式。
还有一个容易忽略的点:DoIP要求ECU必须支持IPv4链路本地地址(169.254.x.x)。这是在没有DHCP服务器时的保底方案。我曾经在客户现场遇到过,整车网络没配DHCP,ECU拿不到IP,诊断仪连不上。后来加上链路本地地址支持,问题解决。