简体   繁体   English

实现 Socket 接口以支持 IPV6 和 IPV4 的最佳方式

[英]Best Way to implement Socket Interface to support both IPV6 and IPV4

What is the best way to implement socket interface to support IPV6.实现套接字接口以支持 IPV6 的最佳方法是什么。 The existing code suppports IPV4 only.现有代码仅支持 IPV4。 Now, to support IPV6 also I have few doubts...现在,要支持 IPV6,我也几乎没有疑问......

1) Should _I replace all the APIs of IPV4 by IPV6 APIs. 1) _我应该用 IPV6 API 替换所有 IPV4 的 API。 Say AF_INET by AF_INET6, sockaddr_in by sockaddr_in6 etc. Will these new APIs support both the protocols.用 AF_INET6 说 AF_INET,用 sockaddr_in6 说 sockaddr_in 等。这些新的 API 是否支持这两种协议。

2) Or should I keep the condition this way... 2)或者我应该保持这种状态......

#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

Please suggest if there is any better way or what is the flaw in the second process.请建议是否有更好的方法或第二个过程中的缺陷是什么。

Technically neither option (1) or (2), you should migrate to IP family agnostic APIs and use struct sockaddr and struct sockaddr_storage instead of IPv4 and IPv6 hardwired structures.从技术上讲,无论是选项 (1) 还是 (2),您都应该迁移到与 IP 系列无关的 API,并使用struct sockaddrstruct sockaddr_storage而不是 IPv4 和 IPv6 硬连线结构。 Stevens' gives good examples of creating an agnostic API, here is a similar method I employed: Stevens 给出了创建不可知 API 的很好的例子,这是我采用的类似方法:

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

Either use a modern network programming library such as Boost.Asio, or (if you want to do it the C/sockets way) the getaddrinfo interface.要么使用现代网络编程库,例如 Boost.Asio,要么(如果你想使用 C/sockets 方式) getaddrinfo接口。 The latter was designed some ten years ago, so it should be available just about everywhere (at least Windows, Linux, BSD, Mac OS X).后者是大约十年前设计的,因此它应该几乎无处不在(至少 Windows、Linux、BSD、Mac OS X)。 It has the added charm that it can also support exotic network protocols, given appropriate OS/C library support, so you can claim to support Protocol-Independent Distributed Cloud Computing®.它还具有额外的魅力,即它还可以支持奇异的网络协议,给定适当的 OS/C 库支持,因此您可以声称支持独立于协议的分布式云计算®。

Depending on target platforms you can set socket options to enable a socket to handle both IPv4 and IPv6 if a suitable dual stack is implemented.根据目标平台,您可以设置套接字选项以使套接字能够同时处理 IPv4 和 IPv6(如果实施了合适的双栈)。 It will remove much of the work in your behalf.它将代表您删除大部分工作。

http://long.ccaba.upc.es/long/045Guidelines/eva/ipv6.html and http://msdn.microsoft.com/en-us/library/bb513665(v=vs.85).aspx may help get started. http://long.ccaba.upc.es/long/045Guidelines/eva/ipv6.html and http://msdn.microsoft.com/en-us/library/bb513665(v=vs.85).aspx may help开始吧。

For many uses it may not be much of a change from your existing IPv4 code.对于许多用途,它可能与您现有的 IPv4 代码没有太大变化。

The other answers are on target, but there's another essential thing to consider: A sockaddr structure is SMALLER THAN the IPv6-required sockaddr_in6 structure.其他答案都在目标上,但还有另一件重要的事情需要考虑: sockaddr 结构比 IPv6 所需的 sockaddr_in6 结构更小。 I was porting code that had this:我正在移植具有以下内容的代码:

struct sockaddr salocal;
struct sockaddr_in * s_in = (struct sockaddr_in *) &salocal;

Replacing the second line with:将第二行替换为:

struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;

leads to problems because, while sockaddr_in fits in a sockaddr , sockaddr_in6 does not, However, sockaddr_storage IS big enough to handle both IPv4 and IPv6.会导致问题,因为虽然sockaddr_in适合sockaddr ,但sockaddr_in6不适合,但是sockaddr_storage足够大,可以同时处理 IPv4 和 IPv6。

Instead switch to something like:而是切换到类似的东西:

struct sockaddr_storage salocal;
struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;

and then, when calling methods like bind, cast to (struct sockaddr *) .然后,当调用 bind 之类的方法时,强制转换为(struct sockaddr *)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM