【问题标题】:Responsing on ICMP in select在选择中响应 ICMP
【发布时间】:2012-01-13 01:30:54
【问题描述】:

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

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 数据报发送到无法访问的端口后返回,触发选择,之后 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)上是否存在类似问题?

【问题讨论】:

  • 您是否只使用一次连接?如果没有,如果您从未收到错误消息告诉您连接不再处于活动状态并且应该关闭,您如何知道何时关闭连接?
  • 我想继续发送数据报,直到远程主机(实际上是一些嵌入式系统)启动或用户终止此操作。
  • 从 Linux 移植应用程序时遇到此错误。在我的情况下,它是 UDP 数据报的非阻塞广播,我根本不想关闭连接,如果客户端死了,我开始在服务器上的 recv 上收到 WSAECONNRESET 错误!似乎错误并不清楚。由 SIO_UDP_CONNRESET 修复,但在我看来就像 Winsock 中的一个错误。

标签: c sockets udp winsock icmp


【解决方案1】:

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

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

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

【讨论】:

  • 我想支持温和的用户中断(实际上这个模块只是软件的一小部分),所以如果有数据,我会定期调用带有超时和recvfrom的select。我想读取数据(如果有),尽可能减少超时,所以我不能使用睡眠;另一方面,如果没有数据,就不应该有任何开销。非常感谢您的回复,我会研究一下。
  • 如果用户“中断”是通过套接字传递的,您可以将其添加到您的select 调用...
  • 不,我的意思是从 UI 中断(=终止)。这段代码在一个特殊的线程中运行,这个线程由另一个模块控制。当然,可以硬终止线程,但我需要小心和受控的退出(对于互斥锁等)。
  • 太棒了!在 UI 和模块之间建立一个套接字;当 UI 想要终止时,将终止命令发送到套接字。这样,您可以立即响应终止命令,而不是等待两秒钟并且您可以删除使select 代码复杂化的超时。
  • 非常感谢,非常有趣的想法。你能指出我在 Linux 和 Windows 上的实现吗(我读过 another SOF topic 对我来说不是很清楚)。
猜你喜欢
  • 1970-01-01
  • 2011-10-10
  • 2023-03-12
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2020-02-22
  • 2019-07-21
  • 2012-01-08
相关资源
最近更新 更多