Windows转Linux程序:CANBUS可读但写入失败,send/write返回-1错误
CAN总线发送失败:errno=6 "No such device or address" 问题解决
问题根源在于你将CAN套接字绑定到了any接口(addr.can_ifindex = 0):
- CAN_RAW套接字允许绑定到
any接口做接收操作,此时会监听所有可用CAN接口 - 但发送操作不支持这种绑定方式,Linux内核无法确定要将帧发送到哪个物理CAN总线,因此返回"No such device or address"错误
修复方案
必须明确指定要发送的物理CAN接口,步骤如下:
- 将接口名称从
"any"替换为实际存在的CAN接口(比如"can0",可通过ip link show命令查看系统中的CAN接口) - 通过
ioctl获取该接口的索引,而非直接设置为0
修改后的代码片段:
int s = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (s < 0) { perror("socket"); return errno; } struct sockaddr_can addr; struct ifreq ifr; addr.can_family = AF_CAN; strcpy(ifr.ifr_name, "can0"); // 替换为你的实际CAN接口名称 // 获取接口索引 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl"); return errno; } addr.can_ifindex = ifr.ifr_ifindex; if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return errno; } // 接收操作正常保留 struct can_frame frame={0}; int nbytes = recv(s, &frame, sizeof(frame), MSG_DONTWAIT); // 现在发送操作可以正常执行 struct can_frame send_frame = {0x123, 2, .data={1, 2}}; nbytes = send(s, &send_frame, sizeof(send_frame), 0);
额外说明
如果需要在运行时动态选择发送接口,也可以不提前绑定套接字,而是使用sendto函数直接指定目标接口的地址:
// 省略绑定步骤,直接构造目标地址 struct sockaddr_can dest_addr; dest_addr.can_family = AF_CAN; dest_addr.can_ifindex = ifr.ifr_ifindex; // 已通过ioctl获取的接口索引 int nbytes = sendto(s, &send_frame, sizeof(send_frame), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
内容的提问来源于stack exchange,提问作者dargaud
相关产品推荐
相关产品推荐

