我正在尝试创建一个套接字,以允许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 ) );
}
答案 0 :(得分:2)
您可以使用IPv6套接字连接到IPv4地址或IPv6地址。 IPv4套接字只能连接到IPv4目标。在服务器端,IPv6套接字可以接受来自IPv6或IPv4的连接,而IPv4套接字只能接受IPv4连接。
你真的应该避免自己解析地址,使用getaddrinfo
。但它不会解析[]
,因此您必须先提取部件。 getaddrinfo
将告诉您是否应使用IPv4套接字或IPv6套接字,但如果您始终要使用IPv6,则可以将ai_family
设置为AF_INET6
,然后添加AI_V4MAPPED
到ai_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