Share via


Dual-Stack sockets para aplicaciones IPv6 Winsock

Para admitir IPv4 e IPv6 en Windows XP con Service Pack 1 (SP1) y en Windows Server 2003, una aplicación tiene que crear dos sockets, un socket para su uso con IPv4 y un socket para su uso con IPv6. La aplicación debe controlar estos dos sockets por separado.

Windows Vista y versiones posteriores ofrecen la capacidad de crear un único socket IPv6 que pueda controlar el tráfico IPv6 e IPv4. Por ejemplo, se crea un socket de escucha TCP para IPv6, se coloca en modo de pila dual y se enlaza al puerto 5001. Este socket de doble pila puede aceptar conexiones de clientes TCP IPv6 que se conectan al puerto 5001 y desde clientes TCP IPv4 que se conectan al puerto 5001. Esta característica permite un diseño de aplicaciones muy simplificado y reduce la sobrecarga de recursos necesaria para las operaciones de contabilización en dos sockets independientes.

Creación de un socket de Dual-Stack

De forma predeterminada, un socket IPv6 creado en Windows Vista y versiones posteriores solo funciona a través del protocolo IPv6. Para convertir un socket IPv6 en un socket de doble pila, se debe llamar a la función setsockopt con la opción de socket IPV6_V6ONLY para establecer este valor en cero antes de que el socket esté enlazado a una dirección IP. Cuando la opción de socket IPV6_V6ONLY se establece en cero, se puede usar un socket creado para la familia de direcciones AF_INET6 para enviar y recibir paquetes hacia y desde una dirección IPv6 o una dirección asignada IPv4.

Direcciones IP con un socket de Dual-Stack

Los sockets de doble pila siempre requieren direcciones IPv6. La capacidad de interactuar con una dirección IPv4 requiere el uso del formato de dirección IPv6 asignado a IPv4. Las direcciones IPv4 deben representarse en el formato de dirección IPv4 asignada a IPv4, lo que permite que una aplicación solo IPv6 se comunique con un nodo IPv4. El formato de dirección IPv4 asignado a IPv6 permite representar la dirección IPv4 de un nodo IPv4 como una dirección IPv6. La dirección IPv4 se codifica en los 32 bits de orden bajo de la dirección IPv6 y los 96 bits de orden superior contienen el prefijo fijo 0:0:0:0:0:0:0:FFFF. El formato de dirección IPv4 asignado a IPv6 se especifica en RFC 4291. Para obtener más información, vea www.ietf.org/rfc/rfc4291.txt. La macro IN6ADDR_SETV4MAPPED en Mstcpip.h se puede usar para convertir una dirección IPv4 al formato de dirección IPv6 asignado a IPv4 necesario.

Si el protocolo subyacente es realmente IPv4, la dirección IPv4 se asigna a un formato de dirección IPv4 asignado a IPv6. Es decir, el campo de familia de la estructura SOCKADDR indica AF_INET6, pero una dirección IPv6 asignada por IPv4 se codifica en la estructura de direcciones IPv6. En el caso de un socket de doble pila en modo de escucha, esto significa que las conexiones IPv4 aceptadas devolverán una dirección IPv6 asignada por IPv4. Para un socket de doble pila que se conecta a un destino IPv4, la estructura SOCKADDR pasada a la conexión debe ser una dirección IPv4 asignada a IPv6. Las aplicaciones deben tener cuidado para controlar estas direcciones IPv6 asignadas por IPv4 de forma adecuada y solo usarlas con sockets de pila dual. Si se va a pasar una dirección IP a un socket IPv4 normal, la dirección debe ser una dirección IPv4 normal no una dirección IPv6 asignada por IPv4.

Posibles problemas al usar un socket de Dual-Stack

Un posible problema para las aplicaciones es obtener una dirección IPv6 asignada por IPv4 en un socket de doble pila y, a continuación, intentar usar la dirección IP devuelta en un socket IPv6 diferente. Por ejemplo, las funciones getockname o getpeername pueden devolver una dirección IPv4 asignada por IPv6 cuando se usa en un socket de pila doble. Si la dirección IPv6 asignada por IPv4 devuelta se usa posteriormente en un socket diferente que no se estableció en doble pila (un socket IPv6 solo que es el comportamiento predeterminado cuando se crea un socket), cualquier uso de este socket IPv6 solo con una dirección IPv6 asignada a IPv4 producirá un error. El formato de dirección IPv4 asignado a IPv6 solo se puede usar en un socket de doble pila.

En un socket de datagramas de doble pila, si una aplicación requiere la función LPFN_WSARECVMSG (WSARecvMsg) para devolver información de paquetes en una estructura WSAMSG para datagramas recibidos a través de IPv4, IP_PKTINFO opción de socket debe establecerse en true en el socket. Si solo la opción IPV6_PKTINFO se establece en true en el socket, se proporcionará información de paquetes para datagramas recibidos a través de IPv6, pero no se puede proporcionar para datagramas recibidos a través de IPv4.

Si una aplicación intenta establecer la opción de socket IP_PKTINFO en un socket de datagramas de doble pila y IPv4 está deshabilitada en el sistema, se producirá un error en la función setsockopt y WSAGetLastError devolverá un error de WSAEINVAL. La función setsockopt también devuelve este mismo error como resultado de otros errores. Si una aplicación intenta establecer una opción de socket de nivel de IPPROTO_IP en un socket de doble pila y se produce un error con WSAEINVAL, la aplicación debe determinar si IPv4 está deshabilitado en el equipo local. Un método que se puede usar para detectar si IPv4 está habilitado o deshabilitado es llamar a la función de socket con el parámetro af establecido en AF_INET para intentar crear un socket IPv4. Si se produce un error en la función de socket y WSAGetLastError devuelve un error de WSAEAFNOSUPPORT, significa que IPv4 no está habilitado. En este caso, la aplicación puede omitir un error de función setsockopt al intentar establecer la opción de socket IP_PKTINFO. De lo contrario, un error al intentar establecer la opción de socket IP_PKTINFO debe tratarse como un error inesperado.

Para un socket de doble pila al enviar datagramas con la función WSASendMsg y una aplicación quiere especificar una dirección de origen IP local específica que se va a usar, el método para controlar esto depende de la dirección IP de destino. Al enviar a una dirección de destino IPv4 o a una dirección de destino IPv4 asignada por IPv4, uno de los objetos de datos de control pasados en la estructura WSAMSG a la que apunta el parámetro lpMsg debe contener una estructura de in_pktinfo que contiene la dirección de origen IPv4 local que se usará para el envío. Al enviar a una dirección de destino IPv6 que no es una dirección IPv4 asignada a IPv6, uno de los objetos de datos de control pasados en la estructura WSAMSG a la que apunta el parámetro lpMsg debe contener una estructura de in6_pktinfo que contiene la dirección de origen IPv6 local que se usará para el envío.

Guía de IPv6 para aplicaciones de Windows Sockets

Cambio de estructuras de datos para las appications de Winsock IPv6

Llamadas de función para aplicaciones IPv6 Winsock

Uso de direcciones IPv4 codificadas de forma rígida

Problemas de la interfaz de usuario para aplicaciones IPv6 Winsock

Protocolos subyacentes para aplicaciones winsock IPv6

getpeername

getsockname

in_pktinfo

in6_pktinfo

IP_PKTINFO

IPV6_PKTINFO

setsockopt

LPFN_WSARECVMSG (WSARecvMsg)

WSASendMsg