2010-03-01 16 views
8

Necesito agregar compatibilidad con IPv6 a una aplicación existente basada en sockets que actualmente solo es compatible con IPv4. Para abarcar la era entrante de IPv6, alguien me ordenó agregar una interfaz IPv6 para la aplicación y dejar que el mundo exterior elija la interfaz IPv4 o la interfaz IPv6 cuando intenta comunicarse con la aplicación.¿Hay alguna diferencia entre IPv4 e IPv6 en el nivel de socket?

Mi pregunta es: ¿es cierto que para el nivel de API de manejo de socket en Linux, no hay diferencia entre manejar un socket basado en IPv4 y un socket basado en IPv6?

Además, ¿es posible dejar que un socket escuche en dos direcciones IP con el mismo puerto? Si eso es cierto, entonces implementar el requisito es un trabajo trivial, supongo.

Respuesta

6

No es posible escuchar en 2 direcciones IP diferentes con 1 socket TCP, sin embargo, si escucha en todas las interfaces usando la dirección in6addr_any, también incluirá todas las direcciones IPv4 (aunque creo que Linux tiene una opción kernel para deshabilitar ese mapeo).

La (nueva versión de) socket API es bastante transparente en cuanto a si está utilizando IPv4 o IPv6, pero se debe tener bastante cuidado sobre cómo una aplicación IPv4 se codifica normalmente.

p. Ej. este código IPv4 que acepta una conexión e imprime la dirección del host remoto:

struct sockaddr_in client_addr; 
socklen_t addr_len = sizeof(client_addr); 
client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len); 
log_printf("New client from %s\n",inet_ntoa(client_addr.sin_addr.s_addr)); 

tendría que ser convertido a la siguiente, que se ocupa de los protocolos IPv4 e IPv6

struct sockaddr_storage client_addr; 
char numeric_addr[INET6_ADDRSTRLEN]; 
socklen_t addr_len = sizeof(client_addr); 
client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len); 
if(client_addr.ss_family == AF_INET) 
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in*)&client_addr)->sin_addr.s_addr ,numeric_addr,sizeof numeric_addr)); 
else if(client_addr.ss_family == AF_INET6) 
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in6*)&client_addr)->sin6_addr ,numeric_addr,sizeof numeric_addr)); 

Aunque te creo podría hacerlo aún más elegante y transparente con getaddrinfo()

Aquí hay notas adicionales sobre IP capa de independencia: http://uw714doc.sco.com/en/SDK_netapi/sockC.PortIPv4appIPv6.html http://www.kame.net/newsletter/19980604/

+0

@nos: gracias por su ayuda. Tengo una pregunta más: ¿es posible vincular un socket udp a más de una dirección IP? por ejemplo, uno para ipv4 y uno para ipv6 totalmente 2. –

+1

No, no puede vincular un socket UDP a más de 1 (o todas) direcciones IP tampoco. Sin embargo, puedes hacerlo con SCTP, utilizando sus funciones de búsqueda múltiple. Fot TCP o UDP tendrías que crear 1 socket para cada dirección en la que quieras escuchar, a menos que desees escuchar todas las direcciones IP – nos

+0

Para obtener sockets de doble pila, hay una opción de socket que habilita o deshabilita el comportamiento de doble pila: busca IPV6_V6ONLY para más información. Si no lo hace, su programa fallará misteriosamente en ciertos sistemas operativos, en versiones específicas. – christopher

0

Creo que hay una diferencia, principalmente cómo se asignan/visualizan las direcciones IP y las máscaras de subred.

Los métodos que toman la dirección IPv4 entrante, no funcionarán y emitirán una excepción si se les proporciona un IPv6 puro, por lo tanto, sus métodos deberán verificar qué tipo de conexión se inició, aparte de eso no creo asi que.

0

IPv6 es el espacio de direcciones de 128 bits y ofrece más características (sin estado, multidifusión, más simple procesamiento de routers, por nombrar sólo algunos) en comparación con IPv4 (que es de 32 bits), el espacio de direcciones IPv4 se está acabando, pero con la ayuda de NAT/SNAT puede aumentar la longevidad del protocolo IPv4. El uso de IPv6 depende de si el sistema operativo puede admitir el nuevo protocolo. Ciertamente está disponible en Windows 7, Linux ... Lo principal es que IPv6 es compatible con versiones anteriores de IPv4 ...

Para responder a su pregunta, eso depende del nivel API siempre que el sistema operativo pueda admitir la pila de red IPv6 , He aquí un ejemplo de IPv6 sockets ejemplo como se encuentra en MSDN, por Linux, el uso de tomas es casi idéntica con la excepción de que se va a utilizar ...

Espero que esto ayude, saludos, Tom .

4

Gran parte del manejo del socket es el mismo para IPv4 e IPv6. En el servidor, una vez que haya enlazado su dirección, las llamadas a listen, accept, recv y send funcionarán igual para las conexiones IPv4 e IPv6.

Pero cualquiera de las funciones que tienen que ver con las direcciones como connect, bind, getsockname, getpeername tendrán que ser modificados como sea necesario utilizar un . Además, debe modificar las funciones que funcionan con la dirección (por ejemplo, las llamadas al inet_addr deben cambiarse al inet_pton).

En Linux, si enlaza a in6addr_any, conexiones IPv4 e IPv6 a ese puerto funcionará (aunque esto podría escuchar a más de 2 direcciones, ya que también va a escuchar en el bucle IPv4 127.0.0.1 y el bucle de retorno IPv6 ::1) . Pero en Windows, nunca he podido hacer que funcione y necesito escuchar en un socket para IPv4 y un socket diferente para IPv6.

+3

En Windows, la capacidad de un solo socket para escuchar y aceptar clientes IPv4 e IPv6 en un solo puerto se introdujo en Vista, a través de su arquitectura de pila de sockets de doble pila rediseñada. Cree un socket de escucha IPv6 y establezca la nueva opción de socket IPV6_V6ONLY en False para permitir clientes IPv4 en él. –

+0

@RemyLeabeauTeamB - gracias - esa información es muy útil. –

2

La guía de programación de redes de Beej trata las diferencias en la codificación de IPv4 e IPv6. http://beej.us/guide/bgnet/

Ha dedicado una sección a cambiar su código IPv4 existente para manejar IPv6.

También explica cómo codificar de forma abstracta en el nivel de socket para que no necesite saber si está tratando con una dirección IPv4 o con un IPv6.

Cuestiones relacionadas