У меня есть приложение Java, которое необходимо подключать через сокеты к двум различным серверам на двух отдельных компьютерах. Один сервер настроен на прослушивание соединений IPv4, а другой настроен на прослушивание соединений IPv6.Java-приложение, которое хочет использовать как Inet4Address, так и Inet6Address в то же время
Теперь, считая, что «host1» - это имя компьютера, прослушивающего соединения IPv4, а «host2» - это имя компьютера сервера, прослушивающего соединения IPv6. Мне нужно, чтобы получить Inet4Address
для «host1» и Inet6Address
для «host2», чтобы создать сокет подключения к каждому серверу, например, следующее:
Inet4Address inet4 = (Inet4Address)InetAddress.getByName("host1");
InetSocketAddress soc4 = new InetSocketAddress(inet4, 7777);
...
Inet6Address inet6 = (Inet6Address)InetAddress.getByName("host2");
InetSocketAddress soc6 = new InetSocketAddress(inet6, 7777);
...
Однако JVM по умолчанию предпочитает использовать адреса IPv4 через IPv6 для соображений обратной совместимости. Итак, в приведенном выше коде первая попытка подключения к «host1» преуспевает, но вторая попытка подключения к «host2» не выполняется, потому что InetAddress.getByName("host2")
возвращает Inet4Address
вместо Inet6Address
.
Я понимаю, что могу установить системное свойство java.net.preferIPv6Addresses
в true, чтобы предпочесть IPv6-адреса по IPv4, но это, в свою очередь, приводит к успешной попытке подключения к «хосту2», но первая попытка подключения к «host1» не удалась (!), потому что InetAddress.getByName("host1")
возвращает Inet6Address
вместо Inet4Address
.
Системное свойство java.net.preferIPv6Addresses
только считывается один раз (см. Строку InetAddress 212-218), и поэтому он не будет иметь эффектов, даже если я изменил его значение на значение false после установки его в true.
Так что я могу сделать в этом случае? Это похоже на общую проблему, поэтому, конечно, должен быть уже способ сделать это.
Обратите внимание, что я могу, конечно, использовать InetAddress.getByAddress()
и предоставить IP-адрес каждого аппарата явно вместо того, чтобы вернуться к Inet4Address
и Inet6Address
, но я не хочу, чтобы это сделать, если я действительно не придется. Так что другие решения, пожалуйста.
О, я использую java 1.6.0_19, если это имеет значение.
Спасибо!
Я делаю. Как я уже сказал, оба сервера прослушивают IPv4 и IPv6-соединения соответственно. Кастинг, который я сделал в приведенном выше примере кода, был просто для того, чтобы показать, что я хотел (и мне нужно) получить «Inet6Address», который затем мне нужно передать в «InetSocketAddress» для подключения к «host2» (передача «Inet4Address» будет причиной сбоя подключения). Так что, хотя я просто использую суперкласс 'InetAddress' все время, под ним на самом деле либо' Inet4Address', либо 'Inet6Address', не так ли? И в этом случае я хотел бы сделать очевидной проблему, с которой я столкнулся, явно делая кастинг. – His
Да, это все равно будет 'Inet4Address' или' Inet6Address', и в чем проблема с ним? IPv6 совместим с IPv4, проблем не должно быть. –
Ну, я не уверен, потому что это не то, что я испытал. Я не могу использовать 'Inet6Address' (или' InetAddress', если хотите) для подключения к серверу, прослушивающему соединение IPv4 - я получаю сбой подключения. Это: 'новый InetSocketAddress (InetAddress.getByName (" host1 "), 7777)' с 'InetAddress.getByName (" host1 ")', возвращающий Inet6Address/InetAddress, не будет работать. Но если 'InetAddress.getByName (« host1 »)' возвращает 'Inet4Address/InetAddress', это сработает. – His