Java-приложение, желающее использовать Inet4Address и Inet6Address одновременно - PullRequest
5 голосов
/ 04 октября 2010

У меня есть Java-приложение, которое должно соединяться через сокеты с двумя разными серверами на двух разных машинах. Один сервер настроен на прослушивание подключений IPv4, а другой - на прослушивание подключений IPv6.

Теперь предположим, что «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, но это, в свою очередь, приводит к второй попытке подключения к "host2", но первая попытка подключения к "host1" Ошибка (!), потому что InetAddress.getByName("host1") возвращает Inet6Address вместо Inet4Address.

Системное свойство java.net.preferIPv6Addresses читается только один раз (см. Строку InetAddress 212-218), и поэтому оно не будет иметь никаких эффектов, даже если я верну ему значение обратно в false после установки его в значение true.

Так что я могу сделать в этом случае? Это кажется общей проблемой, поэтому, безусловно, должен быть способ сделать это.

Обратите внимание, что я, конечно, могу использовать InetAddress.getByAddress() и явно указывать IP-адрес каждой машины, чтобы получить Inet4Address и Inet6Address, но я не хочу этого делать, если мне действительно не нужно. Так что другие решения, пожалуйста.

О, я использую Java 1.6.0_19 на случай, если это имеет значение.

Спасибо!

Ответы [ 3 ]

5 голосов
/ 06 октября 2010
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 голосов
/ 06 октября 2010

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

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

0 голосов
/ 04 октября 2010

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

Таким образом, вам не нужно будет разыгрывать и рисковать, чтобы получить CCE.

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

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


Ресурсы:

...