第2章:DoIP物理层与传输层
各位同学,咱们今天聊聊DoIP的底层基础——物理层和传输层。说实话,很多做诊断的朋友一上来就扎进应用层协议里,结果遇到通信问题就抓瞎了。我个人习惯是,先把底层的路铺好,再谈上层怎么跑。
2.1 以太网物理层基础
DoIP跑在以太网上,这跟传统的CAN总线完全是两码事。CAN是两根线,差分信号,简单可靠。以太网呢?至少四根线,还得考虑阻抗匹配、信号衰减这些事。
物理层到底管什么?
说白了,物理层就是负责把0和1变成电信号,再从电信号还原成0和1。在DoIP场景下,我们常用的是100BASE-TX(百兆)和1000BASE-T(千兆)。
| 标准 | 速率 | 线缆 | 最大距离 |
|---|---|---|---|
| 100BASE-TX | 100 Mbps | Cat 5e | 100米 |
| 1000BASE-T | 1000 Mbps | Cat 5e/6 | 100米 |
我在项目中遇到过一个问题:某款ECU在实验室里通信正常,装车后就频繁断连。查了半天,发现是线束供应商用了劣质网线,阻抗不匹配导致信号反射。嗯,这里要注意——车载环境下的线缆质量,真的不能省。
2.2 TCP/UDP协议在DoIP中的应用
到了传输层,我们面对的是两个老熟人:TCP和UDP。你可能会问,为什么DoIP两个都要用?
TCP:可靠但慢
TCP有三次握手、确认重传、流量控制这些机制。说白了,它保证你发的数据包一定能到达对端,而且顺序不乱。DoIP的诊断消息(比如读取故障码、写入数据)都用TCP。为什么?因为诊断操作要求可靠性,丢一个包可能就导致整个诊断流程失败。
UDP:快但不可靠
UDP就简单多了,发出去就不管了。DoIP的车辆发现、路由激活这些控制消息用UDP。你想想看,车辆发现需要广播,如果用TCP,每个ECU都要建立连接,那效率太低了。
我记得有一次调试,发现诊断请求总是超时。抓包一看,TCP重传了好几次才成功。原来是网络中有丢包,TCP的拥塞控制机制把发送窗口缩小了。后来优化了网络环境,问题就解决了。
2.3 DoIP端口号与套接字
端口号这东西,说白了就是给应用程序用的门牌号。DoIP标准里定义了两个关键端口:
- UDP端口13400:用于车辆发现和路由激活
- TCP端口13400:用于诊断数据交换
为什么都用13400?这是ISO 13400标准规定的,好记。你想想看,如果端口号乱七八糟,那不同厂商的设备怎么互操作?
套接字编程示例
咱们来看一个简单的Python示例,创建一个DoIP的TCP服务端:
import socket
# 创建TCP套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定到DoIP端口
server_address = ('0.0.0.0', 13400)
sock.bind(server_address)
# 开始监听
sock.listen(5)
print('DoIP服务端已启动,等待连接...')
while True:
connection, client_address = sock.accept()
print(f'收到来自 {client_address} 的连接')
# 接收数据
data = connection.recv(4096)
if data:
print(f'收到数据: {data.hex()}')
# 这里可以添加DoIP协议解析逻辑
# ...
connection.close()
关于套接字,还有一点要注意:地址族。DoIP支持IPv4和IPv6。目前大多数车载网络还是用IPv4,但新车型已经开始支持IPv6了。我个人建议,新项目直接上IPv6,省得以后还要做地址转换。
嗯,到这里,物理层和传输层的内容就差不多了。下一章咱们聊聊DoIP的车辆发现机制,这可是DoIP的亮点之一。