2. DoIP车辆识别请求响应
任务目标
实现一个DoIP(Diagnostic over IP)车辆识别请求的响应处理逻辑。当客户端发送0x0004(车辆识别请求)时,服务端应返回包含VIN码和逻辑地址的0x0005(车辆识别响应)报文。
协议背景
DoIP协议中,车辆识别请求(Payload Type = 0x0004)用于发现网络中的车辆ECU。请求报文无负载数据,响应报文(Payload Type = 0x0005)需携带VIN码(17字节ASCII)和逻辑地址(2字节)。本案例聚焦于服务端对该请求的解析与响应构造,不涉及TCP连接管理或路由激活等前置流程。
核心实现
#include <stdint.h>
#include <string.h>
#include <arpa/inet.h>
#define DOIP_HEADER_LEN 8
#define VIN_LEN 17
#define LOGICAL_ADDR_LEN 2
/* DoIP通用报文头 */
typedef struct {
uint8_t version;
uint8_t inverse_version;
uint16_t payload_type;
uint32_t payload_len;
} doip_header_t;
/* 车辆识别响应负载 */
typedef struct {
char vin[VIN_LEN]; /* 17字节ASCII码 */
uint16_t logical_addr; /* 网络字节序 */
} vehicle_id_resp_t;
/**
* @brief 处理车辆识别请求,生成响应报文
* @param vin 车辆VIN码(17字节,不足补空格)
* @param logical_addr ECU逻辑地址(主机字节序)
* @param out_buf 输出缓冲区(需≥8+17+2=27字节)
* @return 响应报文总长度,失败返回-1
*/
int handle_vehicle_id_request(const char *vin, uint16_t logical_addr,
uint8_t *out_buf)
{
if (!vin || !out_buf) {
return -1;
}
doip_header_t *hdr = (doip_header_t *)out_buf;
vehicle_id_resp_t *resp = (vehicle_id_resp_t *)(out_buf + DOIP_HEADER_LEN);
/* 填充报文头 */
hdr->version = 0x02; /* DoIP ISO 13400-2:2012 */
hdr->inverse_version = 0xFD; /* 0x02取反 */
hdr->payload_type = htons(0x0005);
hdr->payload_len = htonl(VIN_LEN + LOGICAL_ADDR_LEN);
/* 填充VIN(不足17字节补空格) */
memset(resp->vin, ' ', VIN_LEN);
memcpy(resp->vin, vin, strnlen(vin, VIN_LEN));
/* 填充逻辑地址(网络字节序) */
resp->logical_addr = htons(logical_addr);
return DOIP_HEADER_LEN + VIN_LEN + LOGICAL_ADDR_LEN;
}
调用示例
#include <stdio.h>
int main(void)
{
uint8_t buf[27];
const char *vin = "LVGBE42K9RG123456"; /* 17位VIN */
uint16_t ecu_addr = 0x0E80; /* 典型ECU逻辑地址 */
int len = handle_vehicle_id_request(vin, ecu_addr, buf);
if (len < 0) {
printf("构造响应失败\n");
return 1;
}
/* 打印响应报文(十六进制) */
for (int i = 0; i < len; i++) {
printf("%02X ", buf[i]);
if ((i + 1) % 8 == 0) printf("\n");
}
printf("\n");
return 0;
}
编译与运行
gcc -o doip_vin doip_vin.c
./doip_vin
验证方法
编译运行后,观察输出报文:
- 前2字节应为
02 FD(版本及反码) - 第3-4字节应为
00 05(Payload Type = 0x0005) - 第5-8字节应为
00 00 00 13(负载长度 = 19字节) - 第9-25字节为VIN码ASCII值,第26-27字节为逻辑地址
0E 80
预期输出首行:02 FD 00 05 00 00 00 13,后续行包含VIN的十六进制ASCII码及结尾的 0E 80。若报文头字段与上述一致,且VIN和逻辑地址正确填入,则判定实现通过。
关键说明
- VIN码必须为17字节,不足时以空格填充(0x20),超过则截断
- 逻辑地址使用
htons()转换为网络字节序,与DoIP协议要求一致 - 本实现仅覆盖车辆识别请求的响应构造,实际应用中需在TCP连接上接收0x0004请求后调用此函数,并将返回的报文发送回客户端