3
votes

I am using raw sockets to send and receive Ethernet data packets in C using recvFrom(). I want to read in non blocking mode so I am using MSG_DONTWAIT. But the recvFrom() is always returning -1 even if packet is received or not. I am new to C programming. I am able to receive my payload but I get message "Receive resource temporary unavailable" always.

Code Snippet:

    if ((sock = socket(AF_PACKET, SOCK_RAW, htons(0x8851))) < 0) { 
       perror("ERROR: Socket");
       exit(1);
    }


    while(1) {
       int flag=0;
       n=recvfrom(sock, buffer, 2048, MSG_DONTWAIT, NULL, NULL);

       if (n == -1) {
           perror("ERROR: Recvfrom");
           close(sock);
           flag=1;

       } 

       if (flag==0)  {
        // Read Packet

       }
    }
1
Why are you creating new sockets in a loop? - user253751
Also, what error does it print? - user253751
I added error message to question. I am closing it too everytime. - Tejzeratul
What do you think should happen if a packet is received while you don't have a socket? (Answer: it will be processed normally like any packet, but your program won't receive a copy because it doesn't have a raw socket) - user253751
It's always returning -1 and EAGAIN because it's never receiving a packet... - user253751

1 Answers

2
votes

If you use the MSG_DONTWAIT argument for recvfrom(), the system call will always immediately return whether or not there is any data to be read. If there's no data, the return value is -1 and then errno will be set to EAGAIN. In your application, I'm not completely sure that MSG_DONTWAIT is the right choice. If the only thing you're doing is reading packets from that one socket, you shouldn't use MSG_DONTWAIT. So, your program in practice will print lots of error messages in a loop. If you remove that error message for the case when errno == EAGAIN, your program would be slightly better but not much better: it would spin in a loop, consuming all CPU resources.

If, however, you are reading from multiple file descriptors at the same time, then using non-blocking I/O is the right choice. But instead of your loop, you should have a loop that polls for the readiness of multiple file descriptors using select(), poll() or epoll_wait(). Since you're running on Linux, I highly recommend epoll_wait() as it's the most scalable approach of these. See the epoll, epoll_wait and epoll_create manual pages on Linux for more information.

I heavily recommend not using MSG_DONTWAIT for now and check if the function call ever returns. If it never returns, it means it isn't receiving any packets.