Проблема
При открытии сокета для IP: 0.0.0.0
и Port: 37845
(просто случайный закрытый порт) с классом сокета Java, подключение к сокету завершается неудачно с java.net.NoRouteToHostException
на Машина 1
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)
Настройка
Machine1:
[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
Machine2:
[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))
- Pinging 0.0.0.0 на Machine1 также работает и разрешается в
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
против SUCCESS