【发布时间】:2019-02-11 18:35:32
【问题描述】:
问题
当使用 java 的套接字类打开IP: 0.0.0.0 和 Port: 37845(只是一个随机关闭的端口)的套接字时,套接字连接失败,机器 1
java.net.NoRouteToHostException
Exception in thread "main" java.net.NoRouteToHostException: No route to host (Host unreachable)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:204)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at Test.main(Test.java:26)
我正在使用这个测试代码:
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
public class Test {
public static void main(String[] args) throws Exception {
Socket socket;
// create a socket with a timeout
SocketAddress socketAddress = new InetSocketAddress("0.0.0.0", 37845);
// create a socket
socket = new Socket();
// this method will block no more than timeout ms.
int timeoutInMs = 10 * 1000; // 10 seconds
socket.connect(socketAddress, timeoutInMs);
System.err.println("SUCCESS");
}
}
预期
什么,我实际上期待的是 java.net.ConnectException : Connection refused (Connection refused),这也是我在另一台 Cent OS 机器上得到的,我们称之为 Machine2:
Exception in thread "main" java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:204)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at Test.main(Test.java:26)
设置
机器 1:
[qa@jenkins-staging ~]$ cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[qa@jenkins-staging ~]$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
[qa@jenkins-staging ~]$ uname -a
Linux jenkins-staging.fancydomain 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
机器 2:
[qa@localhost ~]$ cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[qa@localhost ~]$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
[qa@localhost ~]$ uname -a
Linux localhost.localdomain 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
所以看起来唯一的区别是内核版本。
我尝试过的其他事情:
-
我用 python 尝试了“相同”的代码,我总是得到一个
ConnectionRefused(在 Machine1 + Machine2 上)import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("0.0.0.0", 37845)) - 在 Machine1 上 Ping 0.0.0.0 也可以正常工作并解析为
127.0.0.1 - 在源代码中将
0.0.0.0替换为127.0.0.1可解决 问题,并引发ConnectionRefused(预期)而不是NoRouteToHostException - 禁用 Firewalld、禁用 SELinux 等
问题
- 这是一个 java 错误吗?如果是这样,为什么它在 Machine2 上工作,即使 他们使用相同的 jdk 和相同的 java 版本?
- 这是一个 Linux 内核错误吗?如果是这样,为什么当我打开它时它与 Python 一起工作 一个到 0.0.0.0 但不是 java 的套接字?我会假设底层 系统调用是相同的。
澄清
在上面的示例中,我使用了一个关闭的端口,仅用于演示目的。如果机器上有一个实际的监听端口,这同样适用,那么它将是ConnectionRefused vs SUCCESS
【问题讨论】:
-
我不知道你为什么要测试这个。无论哪种方式都是无效的。
-
@user207421 最初是因为这个:github.com/jenkinsci/docker-plugin/pull/720,但现在我很困扰两台机器的行为不同,我不知道为什么。
标签: java python sockets networking linux-kernel