2010-10-04 6 views
5

У меня есть приложение 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, если это имеет значение.

Спасибо!

ответ

5
static Inet6Address getInet6AddressByName(String host) throws UnknownHostException, SecurityException 
{ 
    for(InetAddress addr : InetAddress.getAllByName(host)) 
    { 
     if(addr instanceof Inet6Address) 
      return (Inet6Address)addr; 
    } 
    throw new UnknownHostException("No IPv6 address found for " + host); 
} 
0

Если у вас нет необходимости в методах, доступных только в Inet6Address или Inet4Address, вам не следует использовать эти классы напрямую, вместо этого используйте InetAddress.

Таким образом, вам не нужно бросать и рисковать иметь CCE.

В вашем случае я действительно не вижу веских причин использовать специально классы IPv6 или IPv4.

Помните, что IPv6 совместим с IPv4, поэтому вам не нужно беспокоиться, когда вы используете IPv4-адрес с системой IPv6.


Ресурсы:

+2

Я делаю. Как я уже сказал, оба сервера прослушивают IPv4 и IPv6-соединения соответственно. Кастинг, который я сделал в приведенном выше примере кода, был просто для того, чтобы показать, что я хотел (и мне нужно) получить «Inet6Address», который затем мне нужно передать в «InetSocketAddress» для подключения к «host2» (передача «Inet4Address» будет причиной сбоя подключения). Так что, хотя я просто использую суперкласс 'InetAddress' все время, под ним на самом деле либо' Inet4Address', либо 'Inet6Address', не так ли? И в этом случае я хотел бы сделать очевидной проблему, с которой я столкнулся, явно делая кастинг. – His

+0

Да, это все равно будет 'Inet4Address' или' Inet6Address', и в чем проблема с ним? IPv6 совместим с IPv4, проблем не должно быть. –

+0

Ну, я не уверен, потому что это не то, что я испытал. Я не могу использовать 'Inet6Address' (или' InetAddress', если хотите) для подключения к серверу, прослушивающему соединение IPv4 - я получаю сбой подключения. Это: 'новый InetSocketAddress (InetAddress.getByName (" host1 "), 7777)' с 'InetAddress.getByName (" host1 ")', возвращающий Inet6Address/InetAddress, не будет работать. Но если 'InetAddress.getByName (« host1 »)' возвращает 'Inet4Address/InetAddress', это сработает. – His

0

Вы пробовали с Inet6Address.getAllByName("host2").

это должно вернуть IPv6 addres хоста, который может быть использован для создания сокета.

+1

'Inet6Address' не имеет конкретной реализации' getAllByName (String) ', поэтому вызов' Inet6Address.getAllByName (String) 'действительно такой же, как вызов статического метода родителя' InetAddress.getAllByName (String) '. – His

 Смежные вопросы

  • Нет связанных вопросов^_^