实现套接字接口以支持 IPV6 和 IPV4 的最佳方法
实现套接字接口支持 IPV6 的最佳方法是什么? 现有代码仅支持 IPV4。现在,为了支持 IPV6,我也没有什么疑问...
1) 是否应该用 IPV6 API 替换 IPV4 的所有 API。比如说 AF_INET 到 AF_INET6,sockaddr_in 到 sockaddr_in6 等等。这些新的 API 是否支持这两种协议。
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
请建议是否有更好的方法或者第二个过程有什么缺陷。
What is the best way to implement socket interface to support IPV6.
The existing code suppports IPV4 only. Now, to support IPV6 also I have few doubts...
1) Should _I replace all the APIs of IPV4 by IPV6 APIs. Say AF_INET by AF_INET6, sockaddr_in by sockaddr_in6 etc. Will these new APIs support both the protocols.
2) Or should I keep the condition this way...
#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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从技术上讲,选项 (1) 或 (2) 都不是,您应该迁移到与 IP 系列无关的 API,并使用 struct sockaddr 和 struct sockaddr_storage 而不是 IPv4 和 IPv6 硬连线结构。 Stevens 给出了创建不可知 API 的好例子,这是我采用的类似方法:
http://code.google.com/p/openpgm/source/browse/trunk/openpgm/pgm/sockaddr.c
Technically neither option (1) or (2), you should migrate to IP family agnostic APIs and use
struct sockaddr
andstruct sockaddr_storage
instead of IPv4 and IPv6 hardwired structures. Stevens' gives good examples of creating an agnostic API, here is a similar method I employed: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 库支持的情况下,它还可以支持外来网络协议,因此您可以声称支持协议无关的分布式云计算®。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. The latter was designed some ten years ago, so it should be available just about everywhere (at least 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®.根据目标平台,如果实现了合适的双堆栈,您可以设置套接字选项以使套接字能够处理 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 代码相比可能没有太大变化。
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. 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.
For many uses it may not be much of a change from your existing IPv4 code.
其他答案都符合目标,但还有另一件重要的事情需要考虑:sockaddr 结构比 IPv6 所需的 sockaddr_in6 结构小。我正在移植具有以下内容的代码:
将第二行替换为:
会导致问题,因为虽然
sockaddr_in
适合sockaddr
,但sockaddr_in6
不适合!但是,sockaddr_storage 足够大,可以同时处理 IPv4 和 IPv6。相反,切换到类似:
然后,当调用像bind这样的方法时,转换为
(struct sockaddr *)
。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. I was porting code that had this:
Replacing the second line with:
leads to problems because, while
sockaddr_in
fits in asockaddr
,sockaddr_in6
does not! However,sockaddr_storage
IS big enough to handle both IPv4 and IPv6.Instead switch to something like:
and then, when calling methods like bind, cast to
(struct sockaddr *)
.