Книга: UNIX: разработка сетевых приложений
12.2. Клиент IPv4, сервер IPv6
12.2. Клиент IPv4, сервер IPv6
Общим свойством узла с двойным стеком является то, что серверы IPv6 могут выполнять обслуживание клиентов IPv4 и IPv6. Это достигается за счет преобразования адресов IPv4 к виду IPv6 (см. рис. А.6). Пример такого преобразования приведен на рис. 12.1.
Рис. 12.1. Сервер IPv6 на узле с двойным стеком, обслуживающий клиенты IPv4 и IPv6
Слева у нас находятся клиент IPv4 и клиент IPv6. Сервер (справа) написан с использованием IPv6 и запущен на узле с двойным стеком. Сервер создал прослушиваемый TCP-сокет IPv6, связанный с универсальным адресом IPv6, и порт TCP 9999.
Мы считаем, что клиент и сервер находятся в одной сети Ethernet. Они могут быть соединены и через маршрутизаторы, поскольку все маршрутизаторы поддерживают и IPv4, и IPv6, но в данном случае это ничего не меняет. В разделе Б.3 описывается другой случай, когда клиенты и серверы IPv6 соединяются через маршрутизаторы, поддерживающие только IPv4.
Мы считаем, что оба клиента посылают сегменты SYN для установления соединения с сервером. Узел клиента IPv4 посылает сегмент SYN и дейтаграмму IPv4, а клиент IPv6 посылает сегмент SYN и дейтаграмму IPv6. Сегмент TCP от клиента IPv4 выглядит в сети как заголовок Ethernet, за которым идет заголовок IPv4, заголовок TCP и данные TCP. Заголовок Ethernet содержит поле типа 0x0800, которое идентифицирует кадр как кадр IPv4. Заголовок TCP содержит порт получателя 9999 (в приложении А рассказывается более подробно о форматах и содержании этих заголовков). IP-адрес получателя в заголовке IPv4, который мы не показываем, — это 206.62.226.42.
Сегмент TCP от клиента IPv6 выглядит в сети как заголовок Ethernet, за которым следует заголовок IPv6, заголовок TCP и данные TCP. Заголовок Ethernet содержит поле типа 0x86dd, которое идентифицирует кадр как кадр IPv6. Заголовок TCP имеет тот же формат, что и заголовок TCP в пакете IPv4, и содержит порт получателя 9999. IP-адрес получателя в заголовке IPv6, который мы не показываем, будет таким: 5f1b:df00:ce3e:e200:20:800:2b37:6426
.
Принимающий канальный уровень просматривает поле типа Ethernet и передает каждый кадр соответствующему модулю IP. Модуль IPv4 (возможно, вместе с модулем TCP) определяет, что сокетом получателя является сокет IPv6, и IPv4-адрес отправителя в заголовке IPv4 заменяется на эквивалентный ему адрес IPv4, преобразованный к виду IPv6. Этот преобразованный адрес возвращается сокету IPv6 как IPv6-адрес клиента, когда функция accept
сервера соединяется с клиентом IPv4. Все оставшиеся дейтаграммы для этого соединения являются дейтаграммами IPv4.
Когда функция сервера accept соединяется с клиентом IPv6, клиентский адрес IPv6 остается таким же, каким был адрес отправителя в заголовке IPv6. Все оставшиеся дейтаграммы для этого соединения являются дейтаграммами IPv6.
Теперь мы можем свести воедино шаги, позволяющие TCP-клиенту IPv4 соединяться с сервером IPv6.
1. Сервер IPv6 запускается, создает прослушиваемый сокет IPv6, и мы считаем, что с помощью функции bind
он связывает с сокетом универсальный адрес.
2. Клиент IPv4 вызывает функцию gethostbyname
и находит запись типа А для сервера. У узла сервера будут записи и типа А, и типа AAAA, поскольку он поддерживает оба протокола, но клиент IPv4 запрашивает только запись типа А.
3. Клиент вызывает функцию connect
, и клиентский узел отправляет серверу сегмент SYN IPv4.
4. Узел сервера получает сегмент SYN IPv4, направленный прослушиваемому сокету IPv6, устанавливает флаг, указывающий, что это соединение использует адреса IPv4, преобразованные к виду IPv6, и отвечает сегментом IPv4 SYN/ACK. Когда соединение установлено, адрес, возвращаемый серверу функцией accept, является адресом IPv4, преобразованным к виду IPv6.
5. Все взаимодействие между клиентом и сервером происходит с использованием дейтаграмм IPv4.
6. Пока сервер не определит при помощи явного запроса, является ли данный IPv6-адрес адресом IPv4, преобразованным к виду IPv6 (с использованием макроопределения IN6_IS_ADDR_V4MAPPED
, описанного в разделе 10.4), он не будет знать, что взаимодействует с клиентом IPv4. Двойной стек протоколов решает эту проблему. Аналогично, клиент IPv4 не знает, что он взаимодействует с сервером IPv6.
Главное в данном сценарии то, что узел сервера с двойным стеком имеет и адрес IPv4, и адрес IPv6. Этот сценарий будет работать, пока используются адреса IPv4.
Сценарий работы UDP-сервера IPv6 аналогичен, но формат адреса может меняться для каждой дейтаграммы. Например, если сервер IPv6 получает дейтаграмму от клиента IPv4, адрес, возвращаемый функцией recvfrom, будет адресом IPv4, преобразованным к виду IPv6. Сервер отвечает на запрос клиента, вызывая функцию sendto
с адресом IPv4, преобразованным к виду IPv6, в качестве адреса получателя. Формат адреса сообщает ядру, что нужно отправить клиенту дейтаграмму IPv4. Но следующей дейтаграммой, полученной сервером, может быть дейтаграмма IPv6, и функция recvfrom
возвратит адрес IPv6. Если сервер отвечает, ядро генерирует дейтаграмму IPv6.
На рис. 12.2 показано, как обрабатывается полученная дейтаграмма IPv4 или IPv6 в зависимости от типа принимающего сокета для TCP и UDP. Предполагается, что это узел с двойным стеком.
Рис. 12.2. Обработка полученных дейтаграмм IPv4 или IPv6 в зависимости от типа принимающего сокета
? Если дейтаграмма IPv4 приходит на сокет IPv4, ничего особенного не происходит. На рисунке изображены две стрелки, помеченные «IPv4»: одна для TCP, другая для UDP. Между клиентом и сервером происходит обмен дейтаграммами IPv4.
? Если дейтаграмма IPv6 приходит на сокет IPv6, ничего особенного не происходит. На рисунке изображены две стрелки, помеченные «IPv6»: одна для TCP. другая для UDP. Между клиентом и сервером происходит обмен дейтаграммами IPv6.
? Когда дейтаграмма IPv4 приходит на сокет IPv6, ядро возвращает соответствующий адрес IPv4, преобразованный к виду IPv6, в качестве адреса, возвращаемого функцией accept (TCP) или recvfrom (UDP). На рисунке это показано двумя штриховыми стрелками. Такое сопоставление возможно, поскольку адрес IPv4 можно всегда представить как адрес IPv6. Между клиентом и сервером происходит обмен дейтаграммами IPv4.
? Обратное неверно: поскольку, вообще говоря, адрес IPv6 нельзя представить как адрес IPv4, на рисунке отсутствуют стрелки от протокола IPv6 к двум сокетам IPv4.
Большинство узлов с двойным стеком должны использовать следующие правила обращения с прослушиваемыми сокетами:
1. Прослушиваемый сокет IPv4 может принимать соединения только от клиентов IPv4.
2. Если у сервера есть прослушиваемый сокет IPv6, связанный с универсальным адресом, и параметр сокета IPV6_V6ONLY (см. раздел 7.8) не установлен, этот сокет может принимать исходящие соединения как от клиентов IPv4, так и от клиентов IPv6. Для соединения с клиентом IPv4 локальный адрес сервера для соединения будет соответствующим адресом IPv4, преобразованным к виду IPv6.
3. Если у сервера есть прослушиваемый сокет IPv6, связанный с адресом IPv6, не являющимся адресом IPv4, преобразованным к виду IPv6, или его сокет связан с универсальным адресом при установленном параметре сокета IPV6_V6ONLY (раздел 7.8), этот сокет может принимать исходящие соединения только от клиентов IPv6.
- Параметр сокета IPV6_NEXTHOP
- 1.6. Таблица соответствия примеров технологии клиент-сервер
- Резюме: совместимость IPv4 и IPv6
- Параметр сокета IPV6_PATHMTU
- 7.8. Параметры сокетов IPv6
- Параметры сокета IPV6_XXX
- 12.3. Клиент IPv6, сервер IPv4
- Запуск InterBase-сервера
- Расширенная установка InterBase-сервера
- Совместимость клиентов и серверов различных версий
- Клиенты 3-го диалекта
- Статистика InterBase-сервера