java - "Connected"UDP套接字接收ICMP端口不可达

标签 java linux sockets udp icmp

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

然而,现在我正在做测试,我发现当我“连接”我的 UDP 客户端套接字时,对该套接字的 write 返回错误,因为服务器已发回ICMP 端口不可达错误..

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

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

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

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

编辑

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

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

最佳答案

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

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

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

对于您在离线时向我指出的 log4j 代码,问题似乎完全出在用户空间代码中。当 log4j UDPAppenderwrite 调用中收到 IOException 时,它只是单方面丢弃套接字,并且没有提供检测该条件的方法,因此你可以修复它。

关于java - "Connected"UDP套接字接收ICMP端口不可达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42021183/

相关文章:

java - 如何从 Linux 的输出中删除(过滤掉)特定的 Java 堆栈跟踪?

python - 对于文件 json 中的键和值

java - 如何构建服务器/客户端协议(protocol)

c# - 使用 NetworkStream 接收文件随机失败,但始终与 Thread.Sleep() 一起使用

java - 需要一些 PUB/SUB Jedis 帮助 Bukkit

java - 有没有办法以编程方式告诉 Java 类的来源?

java - Gridbag布局问题

python - 如何在 .cfg 文件中存储带 # 的单词

linux - Linux 中的 PID 文件

c++ - boost::asio 返回 http 301 错误代码,而 fiddler 没有错误