Search code examples
clinuxsocketsraw-sockets

reading Ethernet data packet from raw sockets using recvfrom() in MSG_DONTWAIT mode


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

       }
    }

Solution

  • 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.