【问题标题】:reading Ethernet data packet from raw sockets using recvfrom() in MSG_DONTWAIT mode在 MSG_DONTWAIT 模式下使用 recvfrom() 从原始套接字读取以太网数据包
【发布时间】:2015-05-20 20:43:46
【问题描述】:

我使用原始套接字在 C 中使用 recvFrom() 发送和接收以太网数据包。我想以非阻塞模式阅读,所以我使用 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 和 EAGAIN 因为它从来没有收到数据包...

标签: c linux sockets raw-sockets


【解决方案1】:

如果你对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 并检查函数调用是否返回。如果它永远不会返回,则意味着它没有收到任何数据包。

【讨论】:

    猜你喜欢
    • 2015-01-09
    • 2019-11-01
    • 1970-01-01
    • 2017-02-16
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    相关资源
    最近更新 更多