сокеты 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, используемый для отправки.
Связанные темы