【问题标题】:Is network byte order pointless under IPv6?IPv6下的网络字节顺序没有意义吗?
【发布时间】:2013-01-13 08:44:11
【问题描述】:

如果我们使用 32 位整数来存储 IPv4 地址,那么必须考虑整数的字节顺序。

但是,由于几乎所有平台下都没有内置的 128 位整数类型,因此 IPv6 地址必须存储到字节数组中,所以,我认为字节顺序不再是问题。

我说的对吗?或者有没有对应IPv6的函数htonlXXX?

【问题讨论】:

  • 你发送的数据呢?
  • 所有数据都可以组织成一个字节流。 IPv6 不关心它发送的数据格式。
  • @xmllmx:因此,IPv4 也不需要它。
  • GCC 为足够多的平台提供了__int128_t,我认为您的“几乎所有平台下都没有内置 128 位整数类型”的说法是错误的。英特尔也提供了类似的类型。
  • "不同系统下字节顺序可能不同。"准确地说,这不会随着 IPv6 而改变。在相同的场景中,字节排序同样重要。也许地址本身可以以不同的方式处理,但其余数据并没有神奇地变得与字节序无关。

标签: c++ c ipv6 ipv4 htonl


【解决方案1】:

IPv6 确实需要 ipv6 地址的网络字节顺序。 hton 和 ntoh 都是关于将地址从您在代码中存储的方式转换为需要在数据包中存储的方式(反之亦然)。所以问题就变成了如何将它存储在代码中。

此外,在代码中定义 IPv6 地址可以允许更多的方式来解决它,而不仅仅是一个字节数组:

struct in6_addr
{
    union 
    {
        __u8 u6_addr8[16];
        __u16 u6_addr16[8];
        __u32 u6_addr32[4];
    } in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};

对于用户来说,IPv6 地址表示为 8 个 16 位值。如果您在代码中将地址存储为 8 个 16 位值,那么您需要在使用 u6_addr16[] 数组将其放入数据包时对每个 16 位值使用 htons,并在检索每个 16 位值时使用 ntohs - 来自 u6_addr16[] 的位值。

这些链接很有帮助:

http://msdn.microsoft.com/en-us/library/ee175867.aspx

http://en.wikipedia.org/wiki/IPv6_address(尤其是右上角的图)

【讨论】:

  • 非常感谢您,mrbultitude。我注意到这是您在 StackOverflow 上的第一篇文章。特别感谢您的两个链接。
  • 你确定这是对的吗?如果您将 IPv4 地址存储为两个 uint16_t 值的数组,则对每一半执行 htons 与对整个 uint32_t 地址执行 htonl 是不同的。
【解决方案2】:

网络字节排序在 2 种情况下很有用。首先,您可以在您所说的地址上使用它。其次,您必须考虑发送数据的字节顺序。您在 cmets 中说 TCP 只是一个字节流是对的,但是许多协议将数字的字节顺序规定为网络顺序。

【讨论】:

    【解决方案3】:

    但是,由于几乎所有平台下都没有内置的 128 位整数类型,因此 IPv6 地址必须存储到字节数组中,所以,我认为字节顺序不再是问题。

    那不符合;在构造字节数组的时候,还是要考虑是按0123456789ABCDEF还是FEDCBA976543210的顺序打包数据。仍然需要正确的字节顺序,只是ntohl()htonl()等函数不适用于生成128位地址。

    例如,如果您使用 inet_ntop() 从“演示文稿”表单生成二进制地址,则您无需自己考虑任一地址类型的字节顺序。字节顺序仍然很重要,但 API 会为您处理。

    【讨论】:

      【解决方案4】:

      在处理 IPv4 地址和端口号时必须密切注意字节顺序的具体原因是结构 sockaddr_inin_addr 具有大于 char 的整数类型的数据成员,其内容必须按网络字节顺序排列。

      即使使用 IPv4,您也可以避免担心地址部分的字节顺序 - 使用 inet_atoninet_pton 直接从字符串填充 in_addr。后一个函数也处理 IPv6 地址(填写 in6_addr)。

      使用 IPv6 时,您仍然需要 htons 作为端口号,如果您选择以大于一个字节的块访问 in6_addr,则需要进行主机/网络转换。

      正如您所说,如果您的平台没有 128 位类型,那么您无法像访问 in_addr 作为单个 32 位块那样访问 in6_addr 作为单个 128 位块位块。但是,如果某些 128 位类型的网络接口/实现确实决定公开它的 128 位视图,那么希望它也能提供匹配的 ntohXhtonX 函数。

      【讨论】:

        【解决方案5】:
        struct in6_addr{
          uint8_t s6_addr[16];//128bit ipv6 address
        };
        

        通过这个结构,你认为是对的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-21
          • 2022-01-22
          • 1970-01-01
          • 2014-05-18
          • 1970-01-01
          • 1970-01-01
          • 2015-03-30
          • 1970-01-01
          相关资源
          最近更新 更多