Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации

Сетевое Руководство пользователя IPv6 для JDK/JRE 5.0

Этот документ затрагивает следующие темы:

Краткий обзор

В течение прошлых нескольких лет IPv6 получил намного большее принятие в отрасли, особенно в определенных областях мира, то есть, Европа и азиатский Тихий океан. Расширяемость, мобильность, качество службы, большего адресного пространства, автоматической конфигурации, безопасности, много-размещения, передачи любому из узлов и многоадресной передачи, и изменения нумерации — они - некоторые из функций IPv6, которые делают это требуемым.

С выпуском J2SE 1.4 в феврале 2002, Java начал поддерживать IPv6 на Солярисе и Linux. Поддержка IPv6 на Windows была добавлена с J2SE 1.5. В то время как другие языки, такие как C и C++ могут поддерживать IPv6, есть некоторые главные преимущества для Java:

Мы докажем эти операторы с примерами кода ниже и обеспечим дополнительные детали о поддержке IPv6.

Поддерживаемые Операционные системы

Следующие операционные системы теперь поддерживаются ссылочной реализацией J2SE:

Используя IPv6 в Java

Используя IPv6 в Java легко; это является прозрачным и автоматическим. В отличие от этого на многих других языках, никакое портирование не необходимо. Фактически, нет никакой потребности даже перекомпилировать исходные файлы.

Рассмотрите пример из Учебного руководства по Java:

Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;

try {
   echoSocket = new Socket("taranis", 7);
   out = new PrintWriter(echoSocket.getOutputStream(), true);
   in = new BufferedReader(new InputStreamReader(
        echoSocket.getInputStream()));
} catch (UnknownHostException e) {
   System.err.println("Don't know about host: taranis.");
   System.exit(1);
} catch (IOException e) {
   System.err.println("Couldn't get I/O for " +
        "the connection to: taranis.");
   System.exit(1);
}
// ... code omitted here
communicateWithEchoServer(out, in);

out.close();
in.close();
stdIn.close();
echoSocket.close();

Можно выполнить тот же самый байт-код для этого примера в режиме IPv6, если и Ваша локальная хост-машина и целевая машина (taranis) являются поддерживающими IPv6.

Напротив, если бы Вы хотели, чтобы соответствующая программа C работала в режиме IPv6, то Вы должны были бы сначала портировать это. Вот то, что должно было бы произойти:

Выборка исходного C кода:

struct sockaddr_in sin;
struct hostent *hp;
int sock;

/* Open socket. */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
   perror("socket");
   return (-1);
}

/* Get host address */
hp = gethostbyname(hostname);
if (hp == NULL || hp->h_addrtype != AF_INET || hp->h_length != 4) {
   (void) fprintf(stderr, "Unknown host '%s'\n", hostname);
   (void) close(sock);
   return (-1);
}

sin.sin_family = AF_INET;
sin.sin_port = htons(port);
(void) memcpy((void *) &sin.sin_addr, (void *)hp->h_addr, hp->h_length);

/* Connect to the host */
if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
   perror("connect");
   (void) close(sock);
   return (-1);
}

Измененный осведомленный о IPv6 код C:

struct addrinfo *res, *aip;
struct addrinfo hints;
int sock = -1;
int error;

/* Get host address. Any type of address will do. */
bzero(&hints, sizeof(hints));
hints.ai_flags = AI_ALL|AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;

error = getaddrinfo(hostname, servicename, &hints, &res);
if (error != 0) {
   (void) fprintf(stderr,
      "getaddrinfo: %s for host %s service %s\n",
      gai_strerror(error), hostname, servicename);
   return (-1);
}
/* Try all returned addresses until one works */
for (aip = res; aip != NULL; aip = aip->ai_next) {
   /*
   * Open socket. The address type depends on what
   * getaddrinfo() gave us.
   */
   sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
   if (sock == -1) {
      perror("socket");

      freeaddrinfo(res);
      return (-1);
   }

/* Connect to the host. */
if (connect(sock, aip->ai_addr, aip->ai_addrlen) == -1)
{
   perror("connect");
   (void) close(sock);
   sock = -1;
   continue;
}
break;
}
   freeaddrinfo(res);

Отметьте, что для новых приложений, если Вы пишете агностические семейством адресом структуры данных, нет никакой потребности в портировании.

Однако, когда дело доходит до программирования серверной стороны в C/C++, есть дополнительная морщина. А именно, в зависимости от того, пишется ли Ваше приложение для платформы двойного стека, такой как Солярис или Linux, или платформа единственного стека, такая как Windows, Вы должны были бы структурировать код по-другому. Для программирования серверной стороны Java показывает большое преимущество. Вы все еще пишете тот же самый код как прежде:

ServerSocket server = new ServerSocket(port);
Socket s;
while (true) {
   s = server.accept();
   doClientStuff(s);
}

Теперь, однако, если Вы выполняете код поддерживающей IPv6 машины, у Вас сразу есть поддерживающая IPv6 служба.

Вот является соответствующий сервер C кодом для платформы двойного стека:

int ServSock, csock;
struct sockaddr addr, from;
...
ServSock = socket(AF_INET6, SOCK_STREAM, PF_INET6);
bind(ServSock, &addr, sizeof(addr));
do {
   csock = accept(ServSocket, &from, sizeof(from));
   doClientStuff(csock);
} while (!finished);

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

Вот код C для того же самого сервера для платформы единственного стека:

SOCKET ServSock[FD_SETSIZE];
ADDRINFO AI0, AI1;
ServSock[0] = socket(AF_INET6, SOCK_STREAM, PF_INET6);
ServSock[1] = socket(AF_INET, SOCK_STREAM, PF_INET);
 ...
bind(ServSock[0], AI0->ai_addr, AI0->ai_addrlen);
bind(ServSock[1], AI1->ai_addr, AI1->ai_addrlen);
 ...
select(2, &SockSet, 0, 0, 0);
if (FD_ISSET(ServSocket[0], &SockSet)) {
   // IPv6 connection csock = accept(ServSocket[0], (LPSOCKADDR)&From, FromLen);
    ...
}
if (FD_ISSET(ServSocket[1], &SockSet))
   // IPv4 connection csock = accept(ServSocket[1], (LPSOCKADDR)&From, FromLen);
    ...
}

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

С Java можно запустить любые приложения Java, клиент или сервер, на поддерживающей IPv6 платформе, используя J2SE 1.4 или позже, и то приложение автоволшебно станет поддерживающим IPv6.

Противопоставляя это с наследством, приложениями родного языка, если бы Вы хотели, чтобы какие-либо приложения C/C++ были поддерживающими IPv6, Вы должны были бы портировать и перекомпилировать их.

Как Работы IPv6 над Платформой Java

Сетевой стек Java сначала проверит, поддерживается ли IPv6 на базовом ОС. Если IPv6 будет поддерживаться, то он попытается использовать стек IPv6. Более определенно на системах двойного стека это создаст сокет IPv6. На отдельном стеке намного более усложняются системные вещи. Java создаст два сокета, один для IPv4 и один для передачи IPv6. Для приложений TCP клиентской стороны, когда-то сокет соединяется, будет фиксирован тип семейства интернет-протокола, и дополнительный сокет может быть закрыт. Для приложений TCP серверной стороны с тех пор нет никакого способа сказать, из которого типа семейства IP прибудет следующий клиентский запрос, два сокета должны быть
сохраняемый. Для приложений UDP оба сокета будут необходимы для времени жизни передачи.

Java получает IP-адрес от службы имен.

Детали о IPv6 поддерживают в Java

Вы не должны знать следующий, чтобы использовать IPv6 в Java. Но если Вам любопытно и что знать то, что происходит при различных обстоятельствах, остаток от этого документа должен обеспечить ответы.

Специальные Типы Адреса IPv6

Неуказанный адрес (:: соответствие 0.0.0.0 в IPv4)

Это также вызывают подстановочный адрес или anylocal. Если сокет связывается с IPv6 anylocal адрес на машине двойного стека, это может принять и IPv6 и трафик IPv4; если это связывается с IPv4 (отображенный на IPv4) адрес anylocal, это может только принять трафик IPv4. Мы всегда пытаемся связать с IPv6 anylocal адрес на машине двойного стека, если связанное системное свойство не устанавливается использовать Стек IPv4.

Когда связано с ::, метод ServerSocket.accept примет соединения от обоих IPv6 или узлов IPv4. У API платформы Java в настоящий момент нет никакого способа определить, чтобы принять соединения только от узлов IPv6.

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

Отметьте: опция, обсужденная ниже, представляется в Draft-ietf-ipngwg-rfc2553bis-03.txt. Это будет поддерживаться в Java 2 платформы, когда это станет стандартом.

Однако, есть новая опция сокета, которая изменяет вышеупомянутое поведение. Draft-ietf-ipngwg-rfc2553bis-03.txt представил новую опцию сокета уровня IP, IPV6_V6ONLY. Эта опция сокета ограничивает сокеты AF_INET6 связью IPv6 только. Обычно, сокеты AF_INET6 могут использоваться и для IPv4 и для связи IPv6. Некоторые приложения могут хотеть ограничить свое использование сокета AF_INET6 к связи IPv6 только. Для этих приложений определяется опция сокета IPV6_V6ONLY. Когда эта опция включается, сокет может использоваться, чтобы отправить и получить пакеты IPv6 только. По умолчанию эта опция выключается.

Петлевой адрес (:: 1 соответствие 127.0.0.1 в IPv4)

Пакеты с петлевым адресом никогда не должны отправляться на ссылке или передаваться маршрутизатором IPv6. Есть два отдельных петлевых адреса для IPv4 и IPv6, и они обрабатываются как таковые.

IPv4 и адреса IPv6 являются отдельными адресными пространствами кроме тех случаев, когда он прибывает в "::".

Адрес совместимости:: w.x.y.z

Это используется для узлов и маршрутизаторов, чтобы динамически туннелировать пакеты IPv6 по инфраструктуре маршрутизации IPv4. Это значимо для ядра ОС и маршрутизаторов. Java обеспечивает служебный метод, чтобы протестировать это.

Отображенный на IPv4 адрес:: ffff:w.x.y.z

Это - адрес IPv6, который используется, чтобы представить адрес IPv4. Это позволяет собственной программе использовать ту же самую структуру данных адреса и также тот же самый сокет, связываясь и с IPv4 и с узлами IPv6. Таким образом, на узле двойного стека с отображенной на IPv4 поддержкой адреса, приложение IPv6 может говорить и с IPv4 и с коллегой IPv6. ОС сделает базовую инфраструктуру, требуемую отправить или получить дейтаграмму IPv4 и вручить ее целевому сокету IPv6, и она синтезирует отображенный на IPv4 адрес IPv6 при необходимости.

Для Java это используется для внутреннего представления; у этого нет никакой функциональной роли. Java никогда не будет возвращать отображенный на IPv4 адрес. Это понимает отображенный на IPv4 синтаксис адреса, и в байтовом массиве и в текстовом представлении. Однако, это будет преобразовано в адрес IPv4.

Связанные с IPv6 Системные Свойства

На машинах двойного стека системные свойства обеспечиваются для того, чтобы они установили привилегированный стек протокола — IPv4 или IPv6 — так же как привилегированное
типы семейства адреса — inet4 или inet6.

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

Эти настройки могут быть изменены через java.net.preferIPv4Stack=<true|false> системное свойство.

По умолчанию мы предпочли бы адреса IPv4 по адресам IPv6, то есть, запрашивая службу имен (например, служба DNS), мы возвратим адреса Ipv4 перед адресами IPv6. Есть две причины этого выбора:

  1. Есть некоторые приложения, которые ожидают, что IPv4 адресует текстовый формат, то есть "%d. % d. % d. % d". Используя IPv4 адрес минимизирует неожиданности;
  2. Используя адрес IPv4, мы можем использовать один вызов (с сокетом IPv6), чтобы достигнуть или наследства служба только для IPv4, или службы IPv6 (если служба IPv6 не находится на Ipv6 только узел).

Эти настройки могут быть изменены через системное свойство java.net.preferIPv6Addresses=<true|false>

Узел двойного стека

Много лет, если не навсегда, будет соединение IPv6 и узлов IPv4 в Интернете. Таким образом совместимость с большой установленной основой узлов IPv4 крайне важна для успеха перехода от IPv4 до IPv6. Двойной стек, определенный в RFC 1933, является одним из основных механизмов для того, чтобы гарантировать гладкий переход. Другой механизм является пакетным туннелированием IPv6, которое относится к JDK только через совместимый с IPv4 адрес. Прежний - самая соответствующая часть к JDK. Двойной стек включает реализации обеих версий интернет-Протокола, IPv4 и IPv6.

Общее свойство узла двойного стека - то, что сокет IPv6 может связаться и с IPv4 и с коллегой IPv6 в транспортном уровне (TCP или UDP). На собственном уровне сокет IPv6 связывается с коллегой IPv4 через отображенный на IPv4 адрес IPv6. Однако, если сокет не проверяет на равноправный тип адреса, он не будет знать, говорит ли он с IPv4 или коллегой IPv6. Вся внутренняя инфраструктура и преобразование типов адреса делаются стеком двойного протокола.

Отметьте: у отображенного на IPv4 адреса есть значение только при реализации стека двойного протокола. Это используется, чтобы фальсифицировать (то есть, чтобы появиться в том же самом формате как), Ipv6 адресуется, чтобы быть переданным к сокету IPv6. На концептуальном уровне у этого нет никакой роли; его роль ограничивается на уровне API Java. Парсинг отображенного на IPv4 адреса поддерживается, но отображенный на IPv4 адрес никогда не возвращается.

Воздействие Приложения Java

  1. Не должно быть никакого изменения в коде программы Java, если все было сделано соответственно. То есть, нет никаких прямых ссылок на адреса литерала IPv4; вместо этого, имена хоста используются.
  2. Вся информация о типе адреса или сокета инкапсулируется в Java сетевой API.
  3. Посредством установки системных свойств могут быть установлены тип адреса и/или предпочтение типа сокета.
  4. Для новых приложений могут использоваться Ipv6-специфичные новые классы и API.

коммуникационные сценарии:

(Узлы) V4 Только V4/V6 V6 Только
V4 Только x x  
V4/V6 x x x
V6 Только   x x

Верхний ряд и оставленный столбец представляют различные типы узла, пытающиеся связываться. X указывает, что эти узлы могут связаться друг с другом.

UDP
сценарий 1:

Или host1 или host2 могут быть собственным приложением.

host1 является сервером, host2 является клиентом

Если host2 будет хотеть говорить с host1, то он создаст сокет V6. Это тогда ищет IP-адрес для host1. С тех пор host1 только имеет v4 стек протокола, у него только будут записи IPv4 в службе поиска имени. Таким образом, host2 попытается достигнуть host1, используя отображенный на IPv4 адрес. Пакет IPv4 будет отправлен host2, и host1 будет думать, что это связывается с v4 клиентом.

host1 является клиентом, host2 является сервером

Если host2 будет сервером, то он сначала создаст сокет v6-типа (по умолчанию), то он будет ожидать соединений. Так как host1 поддерживает v4 только, это создает сокет v4-типа. Они разрешают имя для host2. Это только получает адрес v4 для host2, так как это не понимает адрес IPv6. Таким образом, это соединяется с host2, используя v4 адрес. v4 пакет будет отправлен на проводе. На host2 двойной стек преобразует v4 пакет в v6 пакет с адресом v4-mapped в этом и передаст это к сокету v6. Серверное приложение обработает это, как будто это - соединение от v6 узла.

Изменения класса

InetAddress

Этот класс представляет IP-адрес. Это обеспечивает хранение адреса, адресные именем методы преобразования, методы преобразования адреса, так же как методы тестирования адреса. В J2SE 1.4, этот класс расширяется, чтобы поддерживать и IPv4 и адреса IPv6. Служебные методы добавляются, чтобы проверить типы адреса и контексты. Два типа адресов, IPv4 и IPv6, может отличить тип Java Inet4Address и Inet6Address.

Два новых подкласса InetAddress создаются: Inet4Address и Inet6Address. V4-и состояние V6-specific и поведения реализуются в этих двух подклассах. Из-за объектно-ориентированного характера Java, приложение обычно только должно иметь дело с InetAddress класс — через полиморфизм это получит корректное поведение. Только, когда это должно получить доступ к семейству протокола определенные поведения, такой как в вызове метода только для IPv6, или когда это хочет знать типы классов IP-адреса, будет это когда-либо узнавать Inet4Address и Inet6Address.

Новые представленные методы:

InetAddress:
isAnyLocalAddress
isLoopbackAddress
isLinkLocalAddress
isSiteLocalAddress
isMCGlobal
isMCNodeLocal
isMCLinkLocal
isMCSiteLocal
isMCOrgLocal
getCanonicalHostName
getByAddr

Inet6Address:
isIPv4CompatibleAddress

InetAddress и Различные службы Именования

До 1.4, InetAddress используемый система сконфигурированная служба имен, чтобы разрешить имена хоста. В 1.4, мы добавили провайдера DNS Java через JNDI для альтернативных поисков имени. Можно сказать JDK использовать этого провайдера, устанавливая несколько системных свойств. Эти системные свойства документируются в системный раздел свойств Java. В будущем мы планируем служить универсальной основой поставщика услуг так, чтобы можно было записать Вашим поставщикам услуг собственного имени.

Word на Сериализации

Все адреса IPv4 представляются в Java как Inet4Address объекты. Они сериализируются как InetAddress объекты, и десериализованный от InetAddress к Inet4Address сохранить обратную совместимость. Адреса IPv6 представляются как Inet6Address и сериализируются как таковые.

Socket, ServerSocket, и DatagramSocket

Из-за объектно-ориентированной природы Java, типы адреса и структуры хранения не представляются на уровне API сокета, таким образом, никакие новые API не необходимы. Существующие API сокета обрабатывают и IPv4 и трафик IPv6.

Выбор которого складывают, чтобы использовать, зависит от следующего:

  1. Базовая поддержка ОС;
  2. Привилегированная установка свойства стека пользователя.

Все поддерживали опции сокета Ipv6, имеют IPv4 дубликаты. Таким образом никакие новые API не были добавлены, чтобы поддерживать опции сокета IPv6. Вместо этого старые API перегружаются, чтобы поддерживать и опции сокета V4 и V6.

MulticastSocket

Снова все API опций сокета перегружаются, чтобы поддерживать многоадресные опции сокета IPv6.

Мы добавили два новых API, чтобы установить/получить сетевые интерфейсы в дополнение к существующему MulticastSocket.setInterface/MulticastSocket.getInterface это берет/возвращается InetAddress экземпляр. Два существующих метода используются, чтобы установить или получить сетевой интерфейс, используемый током MulticastSocket отправить многоадресные пакеты (то есть, эквивалентный IP_MULTICAST_IF в собственной опции сокета). Для IPv4 интерфейс был обозначен IP-адресом. Таким образом мы можем использовать эквивалент InetAddress в Java. Они будут продолжать работать с многоадресным сокетом IPv6. Однако, в IPv6, согласно RFC 2553, интерфейс должен быть обозначен, используя интерфейсный индекс. Чтобы лучше поддерживать понятие сетевого интерфейса, мы представляли новый класс, NetworkInterface. Это инкапсулирует данные, представляющие состояние сетевого интерфейса, включая имя и IP-адреса и некоторые основные методы манипулирования. Таким образом мы представили два новых метода для того, чтобы установить исходящий интерфейс для многоадресного сокета: setNetworkInterface и getNetworkInterface. Они берут или возвращают a NetworkInterface объект. Эти новые методы могут использоваться и с v4 и с многоадресной передачей v6.

Методы были также добавлены для присоединения и отъезда многоадресной группы на сетевом интерфейсе. Это было ранее недоступно в API Java.

MulticastSocket:
NetworkInterface getNetworkInterface() setNetworkInterface(NetworkInterface netIf) joinGroup(SocketAddress mcastaddr,NetworkInterface netIf) leaveGroup(SocketAddress mcastaddr,NetworkInterface netIf)

URL, URI синтаксические анализаторы

Литеральные IP-адреса могут использоваться в URL/URI. Однако, начиная с двоеточия (:) используется в существующих спецификациях URL/URI, чтобы разделить узел от порта, используя литеральное представление IPv6 в URL/URI без модификации перестанет работать в парсинге. Таким образом для того, чтобы определить литеральные адреса IPv6 в URL/URI, RFC 2732 создавался. Парсинг URL/URI был обновлен, чтобы быть совместимым с RFC 2732.

SocketPermission

С тех пор SocketPermission использует URL, его реализация была обновлена, чтобы быть совместимой с RFC 2732.

codebase, используемый в определении разрешения, разновидность URL. Также, это должно следовать за форматами URL и соглашениями. Формат RFC 2732 используется для URL и codebase; Формат RFC 2373 еще используется всюду.

Сетевые Свойства IPv6

java.net.preferIPv4Stack (default: false)

Если IPv6 будет доступен на операционной системе, то базовый собственный сокет будет сокетом IPv6. Это позволяет Java (ТМ) приложения соединяться также, и принимать соединения от, оба IPv4 andIPv6 узлы.

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

java.net.preferIPv6Addresses (default: false)

Если IPv6 доступен на операционной системе, предпочтение по умолчанию должно предпочесть отображенный на IPv4 адрес по адресу IPv6. Это по причинам обратной совместимости — например, приложения, которые зависят от доступа к службе только для IPv4, или приложений, которые зависят от %d. % d. % d. % d представление IP-адреса.
Это свойство может быть установлено попытаться изменить предпочтение, чтобы использовать адреса IPv6 по адресам IPv4. Это позволяет приложениям быть протестированными и развернутыми в средах, где приложение, как ожидают, соединится со службами IPv6.

Настройки поставщика услуг DNS JNDI:

sun.net.spi.nameservice.provider.<n>=<default|dns,sun|...>

Определяет провайдера службы имен, которого можно использовать. По умолчанию Java будет использовать сконфигурированный системой, механизм поиска имени, такой как файл, Нис, и т.д. Можно определить свое собственное, устанавливая эту опцию. <n> принимает значение положительного числа, и оно указывает на порядок приоритета: небольшое число берет выше precendence по большему числу. В 1.4, мы обеспечили одного провайдера службы имен DNS через JNDI, который вызывают dns,sun.

sun.net.spi.nameservice.nameservers=<server1_ipaddr,server2_ipaddr ...>

Можно определить список разделенных запятой значений IP-адресов, которые указывают на серверы DNS, которые Вы хотите использовать.

sun.net.spi.nameservice.domain=<domainname>

Это свойство определяет доменное имя DNS по умолчанию, например, eng.example.com.

 


Oracle и/или его филиалы Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами