实现套接字接口支持IPV6和IPV4的最佳方式

Best Way to implement Socket Interface to support both IPV6 and IPV4

本文关键字:IPV4 最佳 方式 IPV6 套接字 接口 支持 实现      更新时间:2023-10-16

实现套接字接口支持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 sockaddrstruct sockaddr_storage而不是IPv4和IPv6硬连线结构。Stevens给出了创建不可知论API的好例子,下面是我使用的类似方法:

http://code.google.com/p/openpgm/source/browse/trunk/openpgm/pgm/sockaddr.c

可以使用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 *)