SocketCAN how to send messages as soon as possible without data loss

908 views Asked by At

I want to measure the maximum speed at which I can send messages via SocketCan from one Raspberry Pi (sender) using PiCan2 to another Raspberry Pi (recipient). The sender reads a 20KiB file, then each byte is sent separately via CAN. The recipient reads the message and saves it on their side to a file. Then I compare if both files are the same.

Initially, I used sleep () and typed the delay from sending each frame.

Then I sent a message and waited for a reply in the form of an empty frame, after which I sent another message.

Now I wanted to use the msg_flags flag and read MSG_CONFIRM to check if the message was delivered, but it doesn't work properly.

How can I read the MSG_CONFIRM flag? Is there another way to send messages as quickly as possible without taking up all of the buffer space and without losing some of the messages?

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

main(void)

{
int i = 0;
int recv_own_msgs = 1;
int flags =0;
int s;
struct msghdr msg;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
char ch;
FILE *fpbr;
ssize_t len;
const char *ifname = "can0";

// *************** read file to send

fpbr = fopen("/home/pi/Desktop/file_to_send.txt", "rb");

 
if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) == -1) 
{
    perror("Error while opening socket");
    return -1;
}

// *******************enable retransmission

setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs));

  


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

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

if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) 
{
    perror("Error in socket bind");
    return -2;
}

msg.msg_flags = 0;

while(1)
{
    ++i;
    
    // read from file to variable
    
    ch = fgetc(fpbr);
    
    frame.can_id  = i;
    frame.can_dlc = 1;
    frame.data[0] = ch;
    
    //send message
    
    write(s, &frame, sizeof(struct can_frame));

    //Here I would like to receive msg_flags after each message is sent and read and use MSG_CONFIRM 
    // to check if the message was correctly received by the other device to be able to send another message
    
    len = recvmsg(s, &msg, flags);

    
    if (msg.msg_flags==MSG_CONFIRM) // msg_flags is 0, not MSG_CONFIRM
    {
        printf("yes");
    }
    
    if (i > 1000)
        {
            break;
        }
    
}

fclose(fpbr);

return 0;
}
0

There are 0 answers