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

Linux下使用SocketCan出现CAN总线Socket读取错误如何解决?

问题排查与修复方案

1. 关键错误点

1.1 接收缓冲区配置层级错误

设置SO_RCVBUF时使用了错误的套接字层级,SO_RCVBUF属于SOL_SOCKET层级,不是SOL_CAN_RAW层级,该错误会导致接收缓冲区配置失效,引发读取异常:

// 错误写法
setsockopt(sdr, SOL_CAN_RAW, SO_RCVBUF, (char *)&sock_buf_size, sizeof(sock_buf_size));

修改为:

setsockopt(sdr, SOL_SOCKET, SO_RCVBUF, (char *)&sock_buf_size, sizeof(sock_buf_size));

1.2 读取返回值变量类型错误

使用int8_t存储read()的返回值不符合规范,read()返回值类型为ssize_t,出错时返回-1,若后续使用CAN FD帧,帧长度超过127时会发生溢出截断,直接导致判断逻辑错误。
修改为:

ssize_t nbytesReceive;

1.3 读取逻辑错误

当前读取逻辑存在两处明显缺陷:

  • 进入while循环前先执行了一次read,读到的有效帧直接被丢弃,无任何处理
  • while循环条件nbytesReceive != 0不符合CAN套接字行为:阻塞模式下CAN套接字无数据时会持续阻塞,不会返回0,只有出错时返回-1,此时必然不等于sizeof(struct can_frame),直接触发报错。

修正后的读取逻辑参考:

int can_receive(void)
{
    struct can_frame frameRead;
    ssize_t nbytesReceive;
    LE_INFO("SDR is: %d ", sdr);
    
    while(1) // 可根据业务需求添加退出条件
    {
        nbytesReceive = read(sdr, &frameRead, sizeof(frameRead));
        if (nbytesReceive < 0)
        {
            // 信号触发的中断可重试,其他错误直接返回
            if (errno == EINTR) continue;
            LE_INFO("Socket reading error, nbytesReceive = %zd, errno = %d", nbytesReceive, errno);
            return SOCK_READING_ERROR;
        }
        else if (nbytesReceive != sizeof(frameRead))
        {
            LE_INFO("Incomplete CAN frame received, len = %zd", nbytesReceive);
            continue;
        }
        else
        {
            LE_INFO("Receive message %X %X %X %X %X %X %X %X %X", frameRead.can_id, frameRead.data[0], frameRead.data[1], frameRead.data[2], frameRead.data[3], frameRead.data[4], frameRead.data[5], frameRead.data[6], frameRead.data[7]);
        }
    }
    return 0;
}

1.4 冗余套接字创建引发资源泄漏

初始化阶段重复调用了socket()创建套接字,第一次创建的套接字未关闭直接被覆盖,属于资源泄漏,删除第一行多余的创建语句即可:

sdr = socket(PF_CAN, SOCK_RAW, CAN_RAW); // 该行多余,直接删除
LE_INFO("sdr è: %d", sdr);
if ((sdr = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)

1.5 过滤器配置校验

当前配置的过滤器仅匹配无RTR标记的标准帧,若实际接收的是扩展帧、带RTR标记的帧,或者ID不在配置的7个ID范围内,都会被过滤器直接丢弃。可临时注释过滤器配置代码,验证无过滤场景下能否正常接收,排查是否为过滤规则匹配问题。

2. 调试建议

  • 报错时打印errno的值,可根据错误码快速定位问题类型
  • 确认CAN接口MTU配置,若为CAN FD设备需要对应调整帧结构和读取长度

内容的提问来源于stack exchange,提问作者kevin94

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 07:45:02