Spec-Zone .ru
спецификации, руководства, описания, API
|
Этот документ затрагивает следующие темы:
В течение прошлых нескольких лет IPv6 получил намного большее принятие в отрасли, особенно в определенных областях мира, то есть, Европа и азиатский Тихий океан. Расширяемость, мобильность, качество службы, большего адресного пространства, автоматической конфигурации, безопасности, много-размещения, передачи любому из узлов и многоадресной передачи, и изменения нумерации — они - некоторые из функций IPv6, которые делают это требуемым.
С выпуском J2SE 1.4 в феврале 2002, Java начал поддерживать IPv6 на Солярисе и Linux. Поддержка IPv6 на Windows была добавлена с J2SE 1.5. В то время как другие языки, такие как C и C++ могут поддерживать IPv6, есть некоторые главные преимущества для Java:
Мы докажем эти операторы с примерами кода ниже и обеспечим дополнительные детали о поддержке IPv6.
Следующие операционные системы теперь поддерживаются ссылочной реализацией J2SE:
Используя IPv6 в 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, то Вы должны были бы сначала портировать это. Вот то, что должно было бы произойти:
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); }
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, Вы должны были бы портировать и перекомпилировать их.
Сетевой стек Java сначала проверит, поддерживается ли IPv6 на базовом ОС. Если IPv6 будет поддерживаться, то он попытается использовать стек IPv6. Более определенно на системах двойного стека это создаст сокет IPv6. На отдельном стеке намного более усложняются системные вещи. Java создаст два сокета, один для IPv4 и один для передачи IPv6. Для приложений TCP клиентской стороны, когда-то сокет соединяется, будет фиксирован тип семейства интернет-протокола, и дополнительный сокет может быть закрыт. Для приложений TCP серверной стороны с тех пор нет никакого способа сказать, из которого типа семейства IP прибудет следующий клиентский запрос, два сокета должны быть
сохраняемый. Для приложений UDP оба сокета будут необходимы для времени жизни передачи.
Java получает IP-адрес от службы имен.
Вы не должны знать следующий, чтобы использовать IPv6 в Java. Но если Вам любопытно и что знать то, что происходит при различных обстоятельствах, остаток от этого документа должен обеспечить ответы.
Это также вызывают подстановочный адрес или 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 только. По умолчанию эта опция выключается.
Пакеты с петлевым адресом никогда не должны отправляться на ссылке или передаваться маршрутизатором IPv6. Есть два отдельных петлевых адреса для IPv4 и IPv6, и они обрабатываются как таковые.
IPv4 и адреса IPv6 являются отдельными адресными пространствами кроме тех случаев, когда он прибывает в "::".
Это используется для узлов и маршрутизаторов, чтобы динамически туннелировать пакеты IPv6 по инфраструктуре маршрутизации IPv4. Это значимо для ядра ОС и маршрутизаторов. Java обеспечивает служебный метод, чтобы протестировать это.
Это - адрес IPv6, который используется, чтобы представить адрес IPv4. Это позволяет собственной программе использовать ту же самую структуру данных адреса и также тот же самый сокет, связываясь и с IPv4 и с узлами IPv6. Таким образом, на узле двойного стека с отображенной на IPv4 поддержкой адреса, приложение IPv6 может говорить и с IPv4 и с коллегой IPv6. ОС сделает базовую инфраструктуру, требуемую отправить или получить дейтаграмму IPv4 и вручить ее целевому сокету IPv6, и она синтезирует отображенный на IPv4 адрес IPv6 при необходимости.
Для Java это используется для внутреннего представления; у этого нет никакой функциональной роли. Java никогда не будет возвращать отображенный на IPv4 адрес. Это понимает отображенный на IPv4 синтаксис адреса, и в байтовом массиве и в текстовом представлении. Однако, это будет преобразовано в адрес IPv4.
На машинах двойного стека системные свойства обеспечиваются для того, чтобы они установили привилегированный стек протокола — IPv4 или IPv6 — так же как привилегированное
типы семейства адреса — inet4 или inet6.
Стек IPv6 предпочитается по умолчанию, с тех пор на машинном сокете IPv6 двойного стека может говорить и с IPv4 и с коллегами IPv6.
Эти настройки могут быть изменены через java.net.preferIPv4Stack=<true|false>
системное свойство.
По умолчанию мы предпочли бы адреса IPv4 по адресам IPv6, то есть, запрашивая службу имен (например, служба DNS), мы возвратим адреса Ipv4 перед адресами 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 адрес никогда не возвращается.
(Узлы) | V4 Только | V4/V6 | V6 Только |
V4 Только | x | x | |
V4/V6 | x | x | x |
V6 Только | x | x |
Верхний ряд и оставленный столбец представляют различные типы узла, пытающиеся связываться. X указывает, что эти узлы могут связаться друг с другом.
Или host1 или host2 могут быть собственным приложением.
Если host2 будет хотеть говорить с host1, то он создаст сокет V6. Это тогда ищет IP-адрес для host1. С тех пор host1 только имеет v4 стек протокола, у него только будут записи IPv4 в службе поиска имени. Таким образом, host2 попытается достигнуть host1, используя отображенный на IPv4 адрес. Пакет IPv4 будет отправлен host2, и host1 будет думать, что это связывается с v4 клиентом.
Если 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. В будущем мы планируем служить универсальной основой поставщика услуг так, чтобы можно было записать Вашим поставщикам услуг собственного имени.
Все адреса IPv4 представляются в Java как Inet4Address
объекты. Они сериализируются как InetAddress
объекты, и десериализованный от InetAddress
к Inet4Address
сохранить обратную совместимость. Адреса IPv6 представляются как Inet6Address
и сериализируются как таковые.
Socket
, ServerSocket
, и DatagramSocket
Из-за объектно-ориентированной природы Java, типы адреса и структуры хранения не представляются на уровне API сокета, таким образом, никакие новые API не необходимы. Существующие API сокета обрабатывают и IPv4 и трафик IPv6.
Выбор которого складывают, чтобы использовать, зависит от следующего:
Все поддерживали опции сокета 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
использует URL, его реализация была обновлена, чтобы быть совместимой с RFC 2732.
codebase
, используемый в определении разрешения, разновидность URL. Также, это должно следовать за форматами URL и соглашениями. Формат RFC 2732 используется для URL и codebase
; Формат RFC 2373 еще используется всюду.
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.
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
.