3

我感兴趣的基本代码序列是(伪代码)

sendto(some host); // host may be unreachable for now which is normal
...
if(select(readfs, timeout)) // there are some data to read
  recvfrom();

自 Win2000 起,ICMP 数据包在将 UDP 数据报发送到无法访问的端口后被发送回,触发 select,之后 recvfrom 失败并显示 WSAECONNRESET。这种行为对我来说是不可取的,因为在这种情况下我希望 select 以超时结束(没有要读取的数据)。在 Windows 上,这可以通过 WSAIoctl SIO_UDP_CONNRESET ( http://support.microsoft.com/kb/263823 ) 解决。

我的问题是:

  1. SIO_UDP_CONNRESET 在这种情况下是最好的方法吗?
  2. 是否有其他方法可以忽略“选择”的 ICMP 或将其过滤为 recvfrom(也许,忽略 Windows 上的 WSAECONNRESET 错误将其视为超时,是否可以在其他情况下触发此错误)?
  3. Linux 和 Unix(Solaris、OpenBSD)上是否有类似的问题?
4

1 回答 1

2

select()readfds设置实际上只是报告read()套接字上的a不会阻塞——它不承诺是否有任何实际数据可供读取。

我不知道你想用两秒钟的超时来完成什么,而不是永远睡觉——也不知道为什么你不能只添加一个块来if检查——但感觉就像你有如果不能很好地处理这种情况,则设计过于复杂。WSAECONNRESETrecvfrom()

许多 Linux 系统上的select_tut(2)联机帮助页都有一些正确使用select(). 以下几条规则似乎最适合您的情况:

   1.  You should always try to use select() without a timeout.
       Your program should have nothing to do if there is no
       data available.  Code that depends on timeouts is not
       usually portable and is difficult to debug.

   ...

   3.  No file descriptor must be added to any set if you do not
       intend to check its result after the select() call, and
       respond appropriately.  See next rule.

   4.  After select() returns, all file descriptors in all sets
       should be checked to see if they are ready.
于 2011-12-05T09:33:53.170 回答