2017-02-03 88 views
2

基于UDP是无连接协议的前提下,我推测主机是否启动或关闭无关紧要。“已连接”UDP套接字接收ICMP端口不可达

但是,现在我正在进行测试,我发现当我连接了我的UDP客户端套接字时,该套接字的write返回错误,因为服务器已发回ICMP端口无法访问错误。

的“连接” UDP端口的目的(根据史蒂文斯UNIX网络编程)是基本上缓存从路由表中的条目,而不是为每个数据包,这是为了一个新的具有性能优势。

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

任何人都可以阐明为什么这可能是什么?有没有已知的解决方法?

我正在使用一个3p java库,没有解决这个问题,只是断开连接,我可能不得不破解它重新连接,但在我之前,我是希望有一些我可以做的(Linux)操作系统级别可能会阻止这种情况的发生......所有对套接字选项的调查都变得毫无意义。

编辑

总之,这是不可能的,固定的代码是这样做的唯一途径。

唯一的可能性似乎是配置iptables阻止ICMP响应,但这是一个大锤来破解这个特定的螺母。

+0

这就是说,我不知道我理解你的问题。您试图将套接字连接到不可用的端点,并且出现ICMP错误。为什么_当你尝试“写”它时,你会得到一个错误? – Alnitak

+0

因为它*无连接* - 的确如果我没有连接,那么我不会得到这个错误。不要被连接的单词误导,只是因为它不是数据报上下文中的含义。就像我说的,史蒂文斯甚至看起来很神秘。 – robert

+0

让我们[在聊天中继续讨论](http://chat.stackoverflow.com/rooms/134756/discussion-between-alnitak-and-robert)。 – Alnitak

回答

3

尽管你的UDP套接字并不是严格“连接”的,但调用connect()确实会为该套接字创建本地“状态”。

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

该连接状态也使得内核,提供与该插座(通过ICMP信号)的应用程序错误 - 未连接的插座没有得到这些 - 他们是“射后不理”。

在你已经向我指出,在离线log4j的代码的情况下,这个问题似乎是完全在用户空间的代码。当它在write调用上获得IOException时,log4j UDPAppender只是单方面丢弃套接字,并且没有提供检测该情况的方法以便您可以修复它。

+0

感谢您的所有帮助和专家的见解。 – robert

-2

嗯,UDP坐在顶部IP。而你得到的信息来自该层。 见https://en.wikipedia.org/wiki/User_Datagram_Protocolhttps://en.wikipedia.org/wiki/Internet_Control_Message_Protocol

所以它在这个意义上无连接,您不具有持久隧道,这样就不能保证你的数据包才能,和东西到达。或者如果出现错误,您不一定会认出来。

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

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

更新:顺便说一句,我认为,你可能会以相反的方式解决问题。您的路由器或其他任何设备可能会忽略这一事实,它不知道 连接 将数据包转发到哪里,并且只是静静地丢弃数据包,而不是用ICMP错误消息回复。

+0

感谢您的洞察丹。现在我已经谈到了这个问题,看起来我们将不得不重写代码。请查看以下有关“已连接”状态如何应用于UDP的说明http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch08lev1sec11.html – robert

+0

您不需要连接UDP套接字。你的最后一段没有意义。 – EJP

+1

好吧,让我稍微改述一下...... :) – Dan