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;
}