高效存储IPv4/IPv6地址的方法

9

我正在开发一个C/C++网络项目,它应该能够同时使用IPv4和IPv6网络协议栈。 该项目仅适用于Linux操作系统。 因此,我试图找到一种有效的方法来存储IP地址并区分协议族。 第一种方法是使用联合体:

struct ip_addr {
   uint8_t fam; // socket family type
   union {
       struct in_addr ipv4_sin_addr;
       struct in6_addr ipv6_sin_addr;
   } addr;
};

第三种方法是使用int128_t/uint128_t或来自gcc的__int128_t。

对于最后一种情况,我想知道从哪个版本的GCC开始支持这些类型,支持哪些平台(特别是IA-32/IA-64),还有是否存在已知的bug。另外,上述解决方案中哪一个可能是最方便的?


1
我不确定int128_t是否适用于IPv6地址。Posix在其API中提供了其他类型。对于GCC,最好使用最新版本(2014年10月的GCC 4.9.1),如果可能的话使用C++11。 - Basile Starynkevitch
3
我建议使用 struct sockaddr_in6 结构体来处理 IPv6 地址。 - πάντα ῥεῖ
你很少会将IP地址用作实际数字(除非它们以网络字节顺序提供)。所以再次强调:使用uint128_t来表示IPv6地址可能是一个非常糟糕的想法! - πάντα ῥεῖ
@πάντα ῥεῖ 我刚刚完成了编辑。 - evelina
1
struct sockaddr_storage 可用于面向用户族群存储,它非常方便,但并非按位紧凑的定义。 - Steve-o
显示剩余5条评论
3个回答

10

第一个答案所述,自GCC 4.6.4起已提供128位整数支持。

你的问题不在于128位整数支持,而是如何正确表示IPv6地址
正确的答案是使用套接字API中可用的struct定义。

这些定义适用于各种操作系统实现的IPv6堆栈,并已标准化。
此外,您无需担心使用这些定义会影响效率。对齐打包将正常工作,您不必关心实际表示的大小端与网络字节顺序问题。


关于您的编辑:

您不需要重新发明轮子!已经有适当的struct定义可正确地处理AF_xxx族类型。

查看这些资源以获取更详细的解释:

我们的生产环境中有一个 IpAddr 类,它使用不透明的 sockaddr_in*sockaddr_in6* 指针来封装基于 sockaddr* 指针的 IPv4 或 IPv6 地址,并根据结构体的 sa_family 成员使用 reinterpret_cast<> 进行转换。请注意保留 HTML 标签。

我曾经看到一个开源项目(chromium)使用了与您提到的类似的表示方法:它使用了一个名为SockaddrStorage [1]的结构体和一个名为IPEndPoint的类来处理这个结构体。 这个结构体的问题在于,当你需要一个端口或者想要创建一个套接字(例如:bind、connect调用)时,它才有用,而不仅仅是用来存储IP地址。 [1] http://goo.gl/hSyW8o - evelina
我需要一种内部存储IP的方法,以便在从字符串表示(例如:从标志或环境变量)转换后进行操作。 我发现使用struct ip_addr更方便,因为它对于像inet_ntop / inet_pton这样的调用更加方便。 无法使用sockaddr(仅作为指针而非单独使用)因为sa_data字段不足以存储IPv6地址。 - evelina
@evelina "我需要一种内部方式来存储IP地址,以便从字符串表示形式(例如:从标志或环境变量)进行转换。" 嗯,我不明白你实际上所担心的是“效率”。所提到的结构将很好地表示IP协议相关类型。 - πάντα ῥεῖ
好的答案。正在使用它。 - Drew

4
根据此线程,在版本4.2左右引入了__int128_t__uint128_t。根据GCC的文档,在GCC 4.6.4及以上版本中支持__int128及其无符号类型unsigned __int128
需要注意的是,一个不可移植的128位整数绝对不是保存和处理IPv6地址的适当类型。如评论中所述,有特殊的数据结构可以使用,例如sockaddr_in6

这解决了128位整数的支持问题,但恐怕那不是IPv6地址表示的正确数据类型 :-/ ... - πάντα ῥεῖ
我已经放上了自己的答案,因为得到了建议。但是指出Y问题可以改进你的答案。 - πάντα ῥεῖ
@Loopunroller 谢谢你的回答!我已经添加了更多关于我的问题的信息。 - evelina

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接