在select中响应ICMP

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以来,发送UDP数据报到不可达端口后返回的ICMP数据包会触发select,之后recvfrom将因WSAECONNRESET而失败。这种行为对我来说并不理想,因为在这种情况下我希望select在超时后完成(没有数据可读取)。在Windows上,可以通过WSAIoctl SIO_UDP_CONNRESET解决此问题 ( http://support.microsoft.com/kb/263823 )。
我的问题是:
  1. 在这种情况下,SIO_UDP_CONNRESET是否是最佳方法?
  2. 是否有其他方法忽略"select"的ICMP或过滤recvfrom的ICMP(也许,在Windows上忽略WSAECONNRESET错误,将其视为超时,可以在其他情况下触发此错误)?
  3. 在Linux和Unix(Solaris、OpenBSD)上是否存在类似的问题?

你只会使用这个连接一次吗?如果不是,那么如果没有错误提示连接已经失效并应该关闭,你如何知道何时关闭连接? - Some programmer dude
我想持续发送数据报,直到远程主机(实际上是一些嵌入式系统)恢复或用户停止这个操作。 - Yury
当我将一个应用程序从Linux移植时,遇到了这个错误。在我的情况下,它是UDP数据报的非阻塞广播,如果客户端死亡,我不想关闭连接,但服务器上的recv会开始出现WSAECONNRESET错误!似乎错误没有被清除。通过使用SIO_UDP_CONNRESET修复了这个问题,但对我来说,这似乎是Winsock中的一个bug。 - dashesy
1个回答

2

select()函数的readfds集合仅表示对套接字进行read()操作时不会阻塞,它并不保证是否有可读数据。

我不知道你为什么要使用两秒的超时而不是永久休眠,也不知道为什么不能添加一个if块来检查recvfrom()中的WSAECONNRESET,但如果无法处理此情况,那么你的设计可能过于复杂。

许多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.

如果用户通过套接字传递“中断”信号,您可以将其添加到您的select调用中... - sarnold
不,我的意思是从用户界面中断(=终止)。这段代码在一个特殊的线程中运行,并且该线程受另一个模块控制。当然,可以强制终止线程,但我需要仔细和有控制的退出(对于互斥等)。 - Yury
太好了!在UI和模块之间建立一个套接字;当UI想要终止时,通过套接字发送终止命令。这样你可以立即响应终止命令,而不是等待两秒钟,还可以删除复杂化select代码的超时限制。 - sarnold
非常感谢,这是一个非常有趣的想法。你能指导我如何在Linux和Windows上实现吗?(我已经阅读了另一个SOF主题,并不是很清楚)。 - Yury
就是这样!涉及TCP似乎有点过头了,但你说得对,如果跨平台是你的目标,那就没问题。 - sarnold
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接