【问题标题】:"Connected" UDP socket receives ICMP Port Unreachable“已连接”的 UDP 套接字接收到 ICMP 端口不可达
【发布时间】:2017-02-03 21:41:52
【问题描述】:

基于 UDP 是一种无连接协议的前提,我假设主机是启动还是关闭是无关紧要的。

但是,现在我正在进行测试,我发现当我“连接”我的 UDP 客户端套接字时,该套接字的 write 会返回错误,因为服务器已发回 ICMP Port Unreachable 错误。 .

“连接”UDP 端口的目的(根据 Stevens Unix Network Programming)基本上是缓存路由表中的条目,而不是创建一个新的每个数据包一个,这应该具有性能优势。

但是,这个 ICMP 数据包导致我丢失了我的客户端套接字,这很烦人。

任何人都可以解释为什么会这样吗?是否有任何已知的解决方法?

我正在使用一个 3p java 库,它不考虑这个问题,只是断开连接,我可能不得不破解它才能重新连接,但在我这样做之前,我有点希望我能在(Linux) 操作系统级别可能会防止这种情况发生……所有对套接字选项等的调查都没有结果。

编辑

总而言之,这是不可能的,修复代码是做到这一点的唯一方法。

似乎唯一的可能性是配置 iptables 来阻止 ICMP 响应,但这有点像大锤来破解这个特殊的坚果。

【问题讨论】:

  • 也就是说,我不确定我是否理解您的问题。您尝试将套接字连接到不可用的端点,并收到 ICMP 错误。当您尝试write 时,为什么不会收到错误消息?
  • 因为它是 connectionless - 实际上,如果我没有连接,那么我就不会收到此错误。不要被连接这个词误导,只是因为这不是它在数据报上下文中的含义。就像我说的那样,史蒂文斯甚至显得很困惑。
  • @EJP 在与 OP 的进一步讨论中,根本问题是 log4j 中 UDPAppender 的一个非常糟糕的实现,它使用连接的套接字,但如果远端消失,则无法提供恢复方法。 bz.apache.org/bugzilla/show_bug.cgi?id=57891
  • 下一段中的文字似乎不正确。它说“recvfrom 可以返回的唯一信息是一个errno 值;recvfrom 无法返回错误数据报的目标IP 地址和目标UDP 端口号”。这很奇怪,因为这正是 address 字段可以用于的用途,似乎 BSD 人员决定在出现 ICMP 错误时不填写它。 WRS 已不在我们身边,但我认识其中一位合著者,可以向他询问。

标签: java linux sockets udp icmp


【解决方案1】:

虽然您的 UDP 套接字不是严格“连接”的,但进行 connect() 调用确实会为该套接字创建本地“状态”。

这种状态不仅允许系统缓存当前路由条目到目的地,而且意味着所有后续的输出操作都不需要指定目的地——它们将使用connect()调用中指定的那个.它还确保内核会丢弃发往您的套接字的、不是来自“已连接”方的入站数据包。

这种连接状态还允许内核将与该套接字(通过 ICMP 发出信号)相关的错误传递给应用程序 - 未连接的套接字不会收到这些错误 - 它们是“一劳永逸”。

在您指出我离线的 log4j 代码的情况下,问题似乎完全出在用户空间代码中。 log4j UDPAppenderwrite 调用上获得IOException 时只是单方面丢弃套接字,并且无法检测该情况以便您修复它。

【讨论】:

  • 感谢您的所有帮助和专家见解。
【解决方案2】:

嗯,UDP 位于 IP 之上。你得到的信息来自那个层。 请参阅https://en.wikipedia.org/wiki/User_Datagram_Protocolhttps://en.wikipedia.org/wiki/Internet_Control_Message_Protocol

所以从某种意义上说,它是无连接的,您没有持久的隧道,因此无法保证您的数据包按顺序到达,等等。否则,如果出现错误,您不一定会立即识别出来。

但你仍然需要能够连接到某些东西,才能开始。它只是发生在较低的水平上。

但是内核仍然会跟踪套接字,所以它可能会通知你它收到的 ICMP 数据包,比如说从沿途的路由器。关键是,ICMP 是下面的一层。

更新:顺便说一句,我认为,您可能会遇到相反的问题。您的路由器或任何介于两者之间的路由器可能会忽略这样一个事实,即它不知道 connect 将数据包转发到哪里,只是默默地丢弃数据包,而不是回复 ICMP 错误消息。

【讨论】:

  • 感谢您的洞察丹。实际上,我现在在这个问题上已经取得了很好的进展,看起来我们将不得不重写代码。查看此内容以了解“已连接”状态如何应用于 UDP masterraghu.com/subjects/np/introduction/…
  • 您不需要连接 UDP 套接字。你的最后一段没有意义。
  • 好的,让我稍微改一下... :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多