You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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接口,步骤如下:

  1. 将接口名称从"any"替换为实际存在的CAN接口(比如"can0",可通过ip link show命令查看系统中的CAN接口)
  2. 通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:12:48