【问题标题】:recv always return EAGAIN but tcpdump shows 0 packets dropped by kernelrecv 总是返回 EAGAIN 但 tcpdump 显示内核丢弃了 0 个数据包
【发布时间】:2021-11-13 18:03:47
【问题描述】:

我正在尝试在循环中使用recv非阻塞模式读取udp数据包,如下所示,但是调用总是返回EAGAIN,但是tcpdump显示0 packets dropped by kernel,这可能是@的原因987654324@?

  for (;;)
  {
    const auto rc = ::recv(fd, data, maxSize, MSG_TRUNC);

    if (rc < 0)
    {
      switch (errno)
      {
        case (EINTR):
          break;

        case (EAGAIN):
          spdlog::error("EAGAIN");

        ...
      }
    }
    else if (rc == 0)
    {
      throw std::runtime_error("Connection closed");
    }
  }

tcpdump ctrl C 返回:

668 packets captured
981 packets received by filter
0 packets dropped by kernel

【问题讨论】:

  • 0 packets dropped by kernel 是怎么回事?这仅仅意味着内核没有自行丢弃任何数据包。在 非阻塞 套接字上获得EAGAIN 是很正常的,这仅意味着在您的recv 时队列中没有数据包。您是说您的应用程序缺少数据包吗?
  • 另外,请注意您应该检查EAGAINEWOULDBLOCK,在这种情况下它们具有相同的含义,但可以具有不同的值。 POSIX 允许返回这两个错误中的任何一个。
  • 你为什么使用非阻塞模式?在这样的自旋循环中使用它是没有意义的。正确的方法是使用select(),但在这样的循环中也是没有意义的。使用阻塞模式。而“内核丢弃的 0 个数据包”是无关紧要的。这并不能证明任何数据报已到达您的套接字。
  • @MarcoBonelli 我虽然队列中没有数据包的原因是因为数据包被内核丢弃了,如果不是这个原因,可能导致recv总是返回EAGAIN ?或者为什么没有数据报到达套接字@user207421?
  • if (rc == 0) ... "Connection closed" - 没有关闭与 UDP 套接字的连接,因为没有连接开始和连接结束,甚至没有真正的连接。此处返回 0 仅表示收到了大小为 0 的数据报,完全有效。

标签: c++ sockets udp tcpdump


【解决方案1】:

0 个被内核丢弃的数据包仅仅意味着内核中的数据包捕获机制没有丢弃任何数据包。它与接收套接字无关。

还要注意,tcpdump 在数据包被防火墙处理之前捕获它们,因此它们很可能被防火墙阻止并且即使 tcpdump 可以捕获这些数据包也不会在套接字上接收到。

此外,在繁忙的循环中调用recv 可能会在大多数情况下返回EAGAIN,因为大多数情况下套接字上没有可用的数据。非阻塞套接字通常与检测套接字活动并在没有活动时阻塞的东西一起使用,即selectpollkqueue,...。结合这些机制允许在单个线程中处理多个套接字。在单个套接字上使用繁忙循环几乎没有意义。

【讨论】:

  • 防火墙已关闭。当我同时启动接收方和发送方时,recv 调用总是返回EAGAIN,看起来数据包从未到达套接字,可能是什么原因?
  • @betteroutthanin: 原因可能是 a) 数据包被防火墙阻止 b) 您试图访问错误的套接字,即套接字绑定到与发送到 c 的 IP、端口不同的 IP、端口)您误解了您所看到的 d)您显示的代码并未反映您实际运行的内容,因此无法发表任何声明。不幸的是,您显示的代码片段不足以重现您的问题。
  • 我以为EAGAIN的返回是因为socket是非阻塞的,原来是SO_RCVTIMEO设置了超时造成的。它实际上是阻塞套接字,仔细检查了上面列出的潜在原因,仍然无法弄清楚为什么它无法从套接字接收任何数据。 nc -l 也没有回应。
【解决方案2】:

都是因为docker主机网络不支持OSX,所以我在容器内部运行的应用程序无法接收到主机发送的UDP数据包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多