<aside> 💡 其實跟 TCP/IP 的方式蠻像的

</aside>


struct canfd_frame

struct canfd_frame {
		canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    len;     /* frame payload length in byte (0 .. 64) */
    __u8    flags;   /* additional flags for CAN FD */
    __u8    __res0;  /* reserved / padding */
    __u8    __res1;  /* reserved / padding */
    __u8    data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
};
typedef __u32 canid_t;
typedef unsigned int __u32;
typedef unsigned char __u8;
#define CANFD_MAX_DLEN 64 
/------------------------/
#define CANFD_MTU (sizeof(struct canfd_frame)) == 72  //canfd_frame

send.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/ioctl.h>
#include <net/if.h>

int main() {
    int s;
    struct sockaddr_can addr;
    struct canfd_frame frame;
    struct ifreq ifr;

    const char *ifname = "vcan0"; //設置CAN名稱

    //創建socket
    if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
        perror("Socket creation error");
        return -1;
    }

    strcpy(ifr.ifr_name, ifname);
    if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
       perror("SIOCGIFINDEX");
       return 1;
	  }

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    int enable_canfd = 1; //open FD mode
		if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_canfd, sizeof(enable_canfd)) < 0) {
	    perror("CAN FD support error");
	    return -1;
		}

    //綁定
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("Binding error");
        return -1;
    }

    
    frame.can_id = 0x123; //dec:291 
    frame.len = 8; 
    frame.flags = CANFD_BRS | CANFD_ESI;

    char mes; //upper[256]
    while(scanf("%s", &mes)){
        strcpy(frame.data, &mes);
        if (write(s, &frame, sizeof(frame)) != sizeof(frame)) {
            perror("Write error");
            return -1;
        }
    }   

    close(s);

    return 0;
}

read.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <sys/ioctl.h>

int main() {
    int s;
    struct sockaddr_can addr;
    struct canfd_frame frame;
    struct ifreq ifr;

    const char *ifname = "vcan0"; //設置CAN名稱

    //創建socket
    if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
        perror("Socket creation error");
        return -1;
    }

    strcpy(ifr.ifr_name, ifname);
    ioctl(s, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    int enable_canfd = 1; //open FD mode
    if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_canfd, sizeof(enable_canfd)) < 0) {
        perror("CAN FD support error");
        return -1;
    }
    
    //綁定
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("Binding error");
        return -1;
    }

    //接收
    while (1) {
        if (read(s, &frame, sizeof(frame)) > 0) {
            printf("can_id : %x\\n", frame.can_id);      //4 byte
            printf("len    : %d\\n", frame.len);         //1 byte  
            printf("flag   : %d\\n", frame.flags);       //1 byte
            //printf("%d\\n", sizeof(frame.__res0));     //1 byte
            //printf("%d\\n", sizeof(frame.__res1));     //1 byte
            //printf("%d\\n", sizeof(frame.data));       //64 byte
            //printf("%d\\n", CANFD_MTU);                //#define CANFD_MTU (sizeof(struct canfd_frame)) == 72  => CAN FD frame
            for (int i = 0; i < frame.len; i++) {
                printf("Data[%d]: %02X\\n", i, frame.data[i]);
            }
            printf("----------\\n");                     //
        }
    }

    close(s);

    return 0;
}