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