Поделиться через


Dual-Stack сокеты для приложений Winsock IPv6

Для поддержки IPv4 и IPv6 в Windows XP с пакетом обновления 1 (SP1) и в Windows Server 2003 приложение должен создать два сокета, один сокет для использования с IPv4 и один сокет для использования с IPv6. Эти два сокета должны обрабатываться отдельно приложением.

Windows Vista и более поздних версий предлагают возможность создать один сокет IPv6, который может обрабатывать трафик IPv6 и IPv4. Например, создается сокет прослушивания TCP для IPv6, помещается в режим двойного стека и привязан к порту 5001. Этот сокет с двойным стеком может принимать подключения от клиентов TCP IPv6, подключающихся к порту 5001 и от клиентов TCP IPv4, подключающихся к порту 5001. Эта функция позволяет значительно упростить проектирование приложения и сократить затраты на ресурсы, необходимые для размещения операций на двух отдельных сокетах.

Создание сокета Dual-Stack

По умолчанию сокет IPv6, созданный в Windows Vista, работает только через протокол IPv6. Чтобы сделать сокет IPv6 в сокет с двумя стеками, функция setockopt должна вызываться с параметром сокета IPV6_V6ONLY, чтобы задать это значение равно нулю, прежде чем сокет привязан к IP-адресу. Если параметр сокета IPV6_V6ONLY имеет значение нулю, то для отправки и получения пакетов из IPv6-адреса или сопоставленного адреса IPv4 можно использовать сокет, созданный для семейства адресов AF_INET6.

IP-адреса с сокетом Dual-Stack

Сокеты с двумя стеками всегда требуют IPv6-адресов. Для взаимодействия с IPv4-адресом требуется использование формата IPv4-сопоставленного IPv6-адреса. Все адреса IPv4 должны быть представлены в формате IPv4-сопоставленного IPv6-адреса, что позволяет приложению IPv6 взаимодействовать только с узлом IPv4. Формат IPv4-сопоставленного IPv6-адреса позволяет представлять IPv4-адрес узла IPv4 в виде IPv6-адреса. IPv4-адрес закодирован в 32-разрядные 32 бита IPv6-адреса, а высокий порядок 96 битов содержит фиксированный префикс 0:0:0:0:0:0:0:FFFF. В RFC 4291 указан формат адресов iPv6, сопоставленный с IPv4. Дополнительные сведения см. в www.ietf.org/rfc/rfc4291.txt. Макрос IN6ADDR_SETV4MAPPED в Mstcpip.h можно использовать для преобразования IPv4-адреса в требуемый формат IPv4-адресов, сопоставленных с IPv6.

Если базовый протокол фактически является IPv4, то IPv4-адрес сопоставляется с форматом IPv4-адресов, сопоставленных с IPv6. То есть поле семейства в структуре SOCKADDR указывает AF_INET6, но ipPv4-сопоставленный IPv6-адрес закодирован в структуре адресов IPv6. Для сокета с двумя стеками в режиме прослушивания это означает, что все принятые подключения IPv4 возвращают ipPv4-адрес, сопоставленный с IPv6. Для сокета с двойным стеком, который подключается к назначению IPv4, структура SOCKADDR, переданная для подключения, должна быть ipPv4-сопоставленным IPv6-адресом. Приложения должны заботиться об обработке этих IPv4-сопоставленных IPv6-адресов соответствующим образом и использовать их только с двумя сокетами стека. Если IP-адрес должен передаваться в обычный сокет IPv4, адрес должен быть обычным IPv4-адресом, а не IPv4-сопоставленным IPv6-адресом.

Потенциальные проблемы с использованием сокета Dual-Stack

Потенциальная ошибка для приложений получает IPv4-сопоставленный IPv6-адрес на сокете с двумя стеками, а затем пытается использовать возвращенный IP-адрес только в другом сокете IPv6. Например, getockname или функции getpeername могут возвращать IPv4-сопоставленный IPv6-адрес при использовании в сокете с двумя стеками. Если возвращенный IPv4-сопоставленный IPv6-адрес затем используется в другом сокете, который не был задан для двойного стека (IPv6 только сокет, который является поведением по умолчанию при создании сокета), любое использование этого сокета IPv6 только с IPv4-сопоставленным IPv6-адресом завершится ошибкой. Формат адресов IPv4, сопоставленный с IPv6, можно использовать только в сокете с двумя стеками.

Если приложению требуется функция LPFN_WSARECVMSG (WSARecvMsg) для возврата сведений о пакете в WSAMSG для диаграмм данных IP_PKTINFO, полученных по протоколу IPv4, необходимо задать значение true в сокете. Если для сокета задано значение true только IPV6_PKTINFO, сведения о пакете будут предоставлены для диаграмм данных, полученных по протоколу IPv6, но могут не предоставляться для диаграмм данных, полученных по протоколу IPv4.

Если приложение пытается задать параметр сокета IP_PKTINFO в сокете с двумя стеками данных и IPv4 отключен в системе, функция setockopt завершится ошибкой, и WSAGetLastError возвращается с ошибкой WSAEINVAL. Эта же ошибка также возвращается функцией setsockopt в результате других ошибок. Если приложение пытается задать параметр сокета уровня IPPROTO_IP на сокете с двумя стеками и завершается сбоем с WSAEINVAL, то приложение должно определить, отключен ли IPv4 на локальном компьютере. Один из методов, который можно использовать для обнаружения включения или отключения IPv4, заключается в вызове функции сокета с параметром af для AF_INET, чтобы попытаться создать сокет IPv4. Если функция сокета завершается ошибкой и WSAGetLastError возвращает ошибку WSAEAFNOSUPPORT, то это означает, что IPv4 не включен. В этом случае сбой функции setockopt при попытке задать параметр сокета IP_PKTINFO можно игнорировать приложением. В противном случае при попытке задать параметр сокета IP_PKTINFO следует рассматривать как непредвиденная ошибка.

Для сокета с двумя стеками при отправке диаграмм данных с помощью функции WSASendMsg и приложение хочет указать конкретный локальный IP-адрес источника, метод обработки этого зависит от целевого IP-адреса. При отправке в адрес назначения IPv4 или ipPv4-сопоставленный адрес назначения IPv6 один из объектов данных управления, передаваемых в структуре WSAMSG, на которую указывает параметр lpMsg, должен содержать структуру in_pktinfo, содержащую локальный исходный адрес IPv4, используемый для отправки. При отправке в целевой адрес IPv6, который не является ipPv4-сопоставленным IPv6-адресом, один из объектов данных управления, передаваемых в структуре WSAMSG, на которую указывает параметр lpMsg, должен содержать in6_pktinfo структуру, содержащую локальный исходный адрес IPv6, используемый для отправки.

руководство по IPv6 для приложений сокетов Windows

изменение структур данных для IPv6 Winsock Appications

вызовы функций для приложений Winsock IPv6

использование жестких IPv4-адресов

проблемы с пользовательским интерфейсом для приложений Winsock IPv6

базовые протоколы для приложений Winsock IPv6

getpeername

возвращает имя

in_pktinfo

in6_pktinfo

IP_PKTINFO

IPV6_PKTINFO

setsockopt

LPFN_WSARECVMSG (WSARecvMsg)

WSASendMsg