实现套接字接口支持IPV6的最佳方式是什么?现有代码只支持IPV4。现在,支持IPV6我也有一些疑问…
1)应该用IPV6 api替换IPV4的所有api吗?AF_INET由AF_INET6, sockaddr_in由sockaddr_in6等等。这些新的api会同时支持这两个协议吗?
或者我应该保持这种状态吗?#ifdef IPV6_SUPPORT
sockaddr_in6 addr;
RTMemoryUtil::memset( &addr, 0, (int)sizeof( addr ) );
addr.sin6_family = AF_INET6;
addr.sin6_port = (unsigned short)htons( port );
RTMemoryUtil::memcpy( &addr.sin6_addr, address, (int)sizeof( *address ) );
#else
sockaddr_in addr;
RTMemoryUtil::memset( &addr, 0, (int)sizeof( addr ) );
addr.sin_family = AF_INET;
addr.sin_port = (unsigned short)htons( port );
RTMemoryUtil::memcpy( &addr.sin_addr, address, (int)sizeof( *address ) );
#endif
请建议是否有更好的方法或者第二道工序有什么缺陷
技术上既不是选项(1)也不是选项(2),您应该迁移到IP族无关的api,并使用struct sockaddr
和struct sockaddr_storage
而不是IPv4和IPv6硬连线结构。Stevens给出了创建不可知论API的好例子,下面是我使用的类似方法:
可以使用Boost等现代网络编程库。Asio,或者(如果你想这样做的C/sockets方式)getaddrinfo
接口。后者是大约十年前设计的,因此它应该可以在任何地方使用(至少Windows, Linux, BSD, Mac OS X)。它还具有额外的魅力,它还可以支持外来的网络协议,给予适当的OS/C库支持,因此您可以声称支持协议独立的分布式云计算®。
如果实现了合适的双栈,则可以根据目标平台设置套接字选项,使套接字能够处理IPv4和IPv6。它将为你省去很多工作。
http://long.ccaba.upc.es/long/045Guidelines/eva/ipv6.html和http://msdn.microsoft.com/en-us/library/bb513665(v=vs.85).aspx可以帮助你开始。
对于许多用途,它可能与您现有的IPv4代码没有太大的变化。
其他答案是正确的,但还有另一个重要的事情要考虑:sockaddr结构小于ipv6要求的sockaddr_in6结构。我移植的代码是这样的:
struct sockaddr salocal;
struct sockaddr_in * s_in = (struct sockaddr_in *) &salocal;
用:
替换第二行struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;
会导致问题,因为sockaddr_in
适合sockaddr
,而sockaddr_in6
不适合!但是,sockaddr_storage
足够大,可以同时处理IPv4和IPv6。
改为:
struct sockaddr_storage salocal;
struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;
,然后,当调用bind等方法时,转换为(struct sockaddr *)
。