"连接" UDP套接字接收ICMP端口无法访问

时间:2017-02-03 09:42:32

标签: java linux sockets udp icmp

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

然而,既然我正在进行测试,我发现当我有"连接"我的UDP客户端套接字,该套接字的write返回错误,因为服务器已发回ICMP端口无法访问错误..

"连接"的目的UDP端口(根据Stevens Unix网络编程)基本上缓存来自路由表的条目,而不是为每个数据包创建一个新的,这应该是有性能优势。

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

有人可以解释为什么会这样吗?有没有已知的解决方法?

我使用的3p java库并没有解释这个问题,只是断开连接,我可能不得不破解它重新连接,但在此之前,我有点希望有我在(Linux)操作系统级别可以做的事情可能是为了防止这种情况发生......所有对套接字选项等的调查都证明是无用的。

修改

总之,这是不可能的,修复代码是唯一的方法。

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

2 个答案:

答案 0 :(得分:3)

虽然您的UDP套接字不是严格的"已连接"但是进行connect()呼叫确实会创建本地"状态"对于那个插座。

此状态不仅允许系统缓存目标的当前路由条目,还意味着所有后续输出操作都不需要指定目标 - 它们将使用在connect()致电。它还确保内核将丢弃发往您的套接字的入站数据包,这些数据包不会来自" connected"方。

这种连接状态还允许内核将与该套接字相关的错误(通过ICMP发出信号)传递给应用程序 - 未连接的套接字无法获取这些 - 他们会“解雇”并且忘记&#34 ;

对于您在离线时指向我的log4j代码,问题似乎完全在用户空间代码中。 log4j UDPAppenderIOException调用时获得write时单方面抛出套接字,并且无法检测到该条件以便您可以修复它。

答案 1 :(得分:-2)

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

所以从某种意义上说它没有连接,你没有持久的隧道,所以不能保证你的数据包按顺序到达,以及东西。或者,如果出现错误,您不一定会立即认出来。

但是你仍然需要能够连接到某些东西。它发生在较低的层次上。

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

更新:顺便说一下,我想,你可以反过来解决这个问题。你的路由器,或者介于两者之间的任何东西都可以忽略这样一个事实:它不知道 connect 将数据包转发到哪里,只是默默地丢弃数据包,而不是回复ICMP错误消息。