Java Socket无法使用NoRouteToHostException(而不是ConnectionRejected)连接到“0.0.0.0”

2024-10-03 06:19:18 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

当用java的socket类打开一个到IP: 0.0.0.0Port: 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)

我正在使用这个测试代码:

^{pr2}$

期望

实际上,我期待的是一个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(在机器1+机器2上)

    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("0.0.0.0", 37845))
    
  • Machine1上ping 0.0.0也同样有效,并解析为127.0.0.1
  • 将源代码中的0.0.0.0替换为127.0.0.1将解析 出现问题,并引发ConnectionRefused(应为)而不是{}
  • 禁用Firewalld、禁用SELinux等

问题

  1. 这是java错误吗?如果是这样,为什么它在机器2上工作 他们使用相同的jdk和相同的java版本?在
  2. 这是Linux内核的错误吗?如果是这样的话,为什么我打开它时它在使用Python 一个0.0.0.0的套接字而不是java?我会假设 系统调用是相同的。在

澄清

在上面的例子中,我使用了一个关闭的端口,只是为了演示。如果机器上有一个实际的监听端口,那么它将是ConnectionRefusedvsSUCCESS


Tags: test机器netmainlinuxconnectsocketjava
3条回答

I inlined the Code you provided and run it on windows 10 system, i get the correct exception

import java.net.InetSocketAddress;
import java.net.Socket;

public class Main {

    public static void main(String[] args) throws Exception {

        new Socket().connect(new InetSocketAddress("0.0.0.0", 37845), 10_0000);
    }
}

Oracle JDK 8.0.202

^{pr2}$

0.0.0.0special address,是特殊0.0.0.0/8范围的一部分,表示“当前网络”或“未指定”。您无法连接到它,因为它未定义为目标。在

这就是为什么你得到一个NoRouteToHostException-地址根本不可路由。如果您尝试运行ping 0.0.0.0或类似的命令,也会遇到类似的失败。在

ConnectionRefused当远程计算机实际拒绝连接时发生,这通常表示远程计算机没有侦听套接字或位于防火墙后面。在

我肯定会在这两台机器上安装Wireshark,并比较所有场景。在

具体来说:

https://superuser.com/questions/720851/connection-refused-vs-no-route-to-host

"Connection refused" means that the target machine actively rejected the connection... one of the following things is likely the reason:

  • Nothing is listening on the port
  • The firewall is blocking the connection with REJECT

The ICMP message, "no route to host," means that ARP cannot find the layer-2 address for the destination host. Usually, this means that that the host with that IP address is not online or responding.

当然,这回避了一个问题,为什么Python的行为方式是一种,而Java的行为方式却不同。。。在同一台机器上。在

再次-我鼓励你看看Wireshark。特别是,看看1)三路TCP握手,2)它前面的ARP调用。在


注:正如马尔特上面所说:

0.0.0.0 ... the address is simply not routable.

{a1}你可以上窗户了

这就引出了一个问题,为什么你会被“拒绝连接”。在

再说一遍-我很好奇Wireshark给你看了什么。在

相关问题 更多 >