“已连接”UDP 套接字接收 ICMP 端口不可达

rob*_*ert 3 java sockets linux udp icmp

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

但是,现在我正在做测试,我发现当我“连接”我的 UDP 客户端套接字时,write该套接字返回一个错误,因为服务器发回了一个 ICMP 端口无法访问错误..

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

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

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

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

编辑

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

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

Aln*_*tak 5

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

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

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

对于您指向我离线的 log4j 代码,问题似乎完全出在用户空间代码中。log4j的UDPAppender只是单方面扔掉时,它得到一个插座IOException上的write电话,并没有提供任何手段来检测条件,这样就可以解决这个问题。