【问题标题】:udp select timeout issues. Either timing out or reading from all clientsudp 选择超时问题。超时或从所有客户端读取
【发布时间】:2014-05-07 08:50:25
【问题描述】:

我正在使用 select 来处理 udp 服务器上的连接。如果我在一段时间内没有收到数据包,我想超时。问题是,似乎我可以正确超时并且只从一个客户端读取,或者从所有客户端读取而不超时。

此功能的不同之处在于选择的第一个参数int nfds

这是我的代码:

int TIMEOUT = 5;
for (;;) {
    FD_ZERO(&read_handles); 
    FD_SET(udpFD, &read_handles); 

    timeout.tv_sec = TIMEOUT;
    timeout.tv_usec = 0;
    if (select(udpFD+1, &read_handles, NULL, NULL, &timeout) == 0) {
        printf("Select has timed out...\n");
        return 1;
    } else {
        int length = 1;
        if (FD_ISSET(udpFD, &read_handles)) {
           //process read.
        }
    }
}

此版本不会超时。如果我将选择行更改为:

if(select(udpFD, &read_handles, NULL, NULL, &timeout) == 0)

它确实超时,但它只接收来自我的一个客户的数据。

udpFD 是我正在查看的唯一句柄,但它的值为 4,因为它不是我创建的第一个描述符。我不知道这是否有区别,因为它是最大值。

如何同时超时并从我的两个客户端获取数据?

【问题讨论】:

  • “不超时”到底是什么意思?你的意思是它永远留在select
  • select 也会在发生错误时返回 (-1),而您并未对其进行测试。如果是这种情况,FD_ISSET 将返回 (0) 是理所当然的。 5 秒是很长的时间 - 如果 EINTR/EAGAIN 是罪魁祸首,我不会感到惊讶。
  • @DavidSchwartz 是的,它会永远留在select
  • @BrettHale 我现在只向它发送两条消息。它也具有相同的行为,但超时时间更短。我不知道这是否会改变问题,但我会检查错误代码,看看是否有影响。
  • @publ1c_stat1c 您是否通过在select 之前和之后记录某些内容来100% 确认这一点?

标签: c++ c select udp timeout


【解决方案1】:

使用if(select(udpFD+1, &read_handles, NULL, NULL, &timeout) == 0) 是正确的方法。

这会奏效。

我的错误出现在我没有重置读取的长度字段的代码中,并且卡在了recvfrom 循环中,并且只调用了一次 select。

【讨论】:

  • 第一个参数应该是 udpFD+1(不是 udpFD)。
  • 有什么原因吗?单独的 udpFD 似乎可以按预期工作。
  • @publ1c_stat1c 因为这是定义方法的方式。该参数是集合中可能的 FD 的数量,根据定义,它是最高 FD 加一。如果您使用的是 Windows,它会被忽略,但无论如何您都应该正确处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 2013-11-13
相关资源
最近更新 更多