8

我正在开发一个 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;
};
第二种方法是定义一个`typedef std::vector IPAddressNumber`并在向量的字节数之后产生差异。

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

对于最后一种情况,我想知道这些类型是从哪个 GCC 版本支持的,针对哪些平台(尤其是 IA-32/IA-64)以及是否有任何已知的错误。另外,上述哪种解决方案可能是最方便的?

4

3 回答 3

10

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

您的问题不是 128 位整数支持,而是如何正确表示 IPv6 地址
对此的正确答案是使用套接字 APIstruct中可用的定义。

这些对于 IPv6 堆栈的各种操作系统实现都是可用的和标准化的。
此外,您无需担心使用这些的效率。对齐打包将正常工作,您不必关心实际表示的字节序与网络字节顺序问题。


至于您的编辑:

您不必重新发明轮子!已经有关于正确族类型的适当struct定义可用。AF_xxx

检查这些资源以获得更详细的解释:

我们IpAddr在生产中有一个类,它使用 opaquesockaddr_in*和指针来封装基于指针和结构成员的sockaddr_in6*IPv4 或 IPv6 地址。sockaddr*reinterpret_cast<>sa_family

于 2014-10-23T17:17:12.347 回答
4

根据这个线程 __int128_t,并__uint128_t在 4.2 版左右引入。并且根据 GCC 的文档,自GCC 4.6.4__int128起支持其未签名的对应物。unsigned __int128

请注意,不可移植的 128 位整数绝对适合保存和使用 IPv6 地址。正如评论中提到的,有一些特殊的数据结构,比如sockaddr_in6.

于 2014-10-23T15:52:54.557 回答
0

这段代码来自 nginx。这与第一个答案相同。我认为使用指针 sockaddr_in* 不是一个好主意。

typedef union {
    struct sockaddr           sockaddr;
    struct sockaddr_in        sockaddr_in;
#if (NGX_HAVE_INET6)
    struct sockaddr_in6       sockaddr_in6;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
    struct sockaddr_un        sockaddr_un;
#endif
} ngx_sockaddr_t;

https://github.com/nginx/nginx/blob/912fb44e25c6ab2598e36b4544c709b871251b2e/src/core/ngx_inet.h#L44

于 2020-09-11T06:51:23.573 回答