我使用哪个地址系列与src IPv4和dest IPv6?

时间:2012-07-05 21:25:54

标签: c windows sockets ipv6 ipv4

我正在尝试创建一个套接字,以允许IPv4到IPv4,IPv4到IPv6,IPv6到IPv4和IPv6到IPv6的地址连接。

1。)协议组合(例如IPv4到IPv6,IPv6到IPv4)是否允许?

2.如果是这样,我是否使用源地址或目标地址的族来创建套接字?

目前我正在使用源地址,并在使用IPv6源地址和IPv4目标地址时收到套接字错误10014 WSAEFAULT。

代码的相关部分:

if ( !strchr( srcAddr, '[' ) )
    sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
else
    sock = socket( AF_INET6, SOCK_STREAM, IPPROTO_TCP );

if ( !strchr( srcAddr, '[' ) )
{
    rc = bind( sock, ( struct sockaddr * ) &sAddrSrc, 
        sizeof( sAddrSrc ) );
}
else
{
    rc = bind( sock, ( struct sockaddr * ) &sAddrSrc6, 
        sizeof( sAddrSrc6 ) );
}

if ( !strchr( destAddr, '[' ) )
{
    rc = connect( sock, (struct sockaddr *) &sAddrDest, 
        sizeof(sAddrDest) );
}
else
{
    rc = connect( sock, ( struct sockaddr * ) &sAddrDest6, 
        sizeof( sAddrDest6 ) );
}

2 个答案:

答案 0 :(得分:2)

您可以使用IPv6套接字连接到IPv4地址或IPv6地址。 IPv4套接字只能连接到IPv4目标。在服务器端,IPv6套接字可以接受来自IPv6或IPv4的连接,而IPv4套接字只能接受IPv4连接。

你真的应该避免自己解析地址,使用getaddrinfo。但它不会解析[],因此您必须先提取部件。 getaddrinfo将告诉您是否应使用IPv4套接字或IPv6套接字,但如果您始终要使用IPv6,则可以将ai_family设置为AF_INET6,然后添加AI_V4MAPPEDai_flags。在这种情况下,如果需要,返回的地址将是::ffff:IPv4,这是IPv6套接字连接到IPv4目的地所需的。

在服务器端,使用IPv6套接字,然后确保调用setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof(int))以使其接受IPv6和IPv4连接。 (请注意,MSVC可能不接受此C99语法。)

如果您说已经使用IPv4源调用bind,反之亦然,则无法连接到IPv6目标,但如果您未在连接端调用bind,则答案适用,或者等到你调用getaddrinfo之后选择要绑定的地址。

答案 1 :(得分:2)

否则您无法连接到与配置套接字的地址不同的地址系列。 IPv6和IPv4使用不同的网络堆栈,因此如果您尝试连接到IPv6端点,则必须使用IPv6作为源地址。

在您的情况下,如果要连接到一个IPv4地址而另一个连接到IPv6地址,则需要2个插槽。

在服务器端,还需要2个套接字来监听IPv4和IPv6。两个套接字都可以绑定到相同的端口号(因为它们都是不同的网络堆栈),但它们将侦听不同的IP地址。

这本电子书对于IPv4和IPv6路由都是一个非常好的参考:Tcp/IP fundamentals for Microsoft Windows