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

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

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

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

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

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

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

Если базовый протокол фактически является IPv4, то IPv4-адрес сопоставляется с форматом IPv6-адресов. Это поле семейства в структуре SOCKADDR указывает AF_INET6, но сопоставленный IPv4-адрес закодирован в структуре IPv6-адресов. Для сокета с двумя стеками в режиме прослушивания это означает, что любые принятые подключения IPv4 будут возвращать IPv4-адрес IPv6. Для сокета с двумя стеками, который подключается к назначению IPv4, структура SOCKADDR, передаваемая для подключения, должна быть IPv4-адресом 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 можно использовать только в сокете с двойным стеком.

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

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

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

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

Изменение структур данных для приложений Winsock для IPv6

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

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

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

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

getpeername

getsockname

in_pktinfo

in6_pktinfo

IP_PKTINFO

IPV6_PKTINFO

setsockopt

LPFN_WSARECVMSG (WSARecvMsg)

WSASendMsg