在MSG_DONTWAIT模式下使用recvfrom()从原始套接字读取以太网数据包

时间:2015-03-18 06:46:25

标签: c linux sockets raw-sockets

我正在使用原始套接字使用recvFrom()在C中发送和接收以太网数据包。我想在非阻塞模式下阅读,所以我使用的是MSG_DONTWAIT。但即使接收到数据包,recvFrom()也总是返回-1。我是C编程的新手。 我能够收到我的有效载荷,但是我收到消息"接收资源暂时不可用"总是

代码段:

    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 个答案:

答案 0 :(得分:2)

如果对recvfrom()使用MSG_DONTWAIT参数,系统调用将始终立即返回是否有任何数据要读取。如果没有数据,则返回值为-1,然后errno将设置为EAGAIN。在您的应用程序中,我不完全确定MSG_DONTWAIT是正确的选择。如果您唯一要做的就是从该套接字读取数据包,则不应使用MSG_DONTWAIT。因此,您的程序在实践中将在循环中打印大量错误消息。如果你在errno == EAGAIN的情况下删除了该错误消息,那么你的程序会稍微好一点但不会好多了:它会循环旋转,占用所有CPU资源。

但是,如果您同时读取多个文件描述符,则使用非阻塞I / O是正确的选择。但是,您应该有一个循环,使用select(),poll()或epoll_wait()来轮询多个文件描述符的准备情况。由于您在Linux上运行,我强烈推荐epoll_wait(),因为它是这些中最具扩展性的方法。有关详细信息,请参阅Linux上的epoll,epoll_wait和epoll_create手册页。

我强烈建议现在不要使用MSG_DONTWAIT并检查函数调用是否会返回。如果它永远不会返回,则表示它没有收到任何数据包。