【问题标题】:Why are linux's IPv4 address taking 16 bytes instead of 4为什么 linux 的 IPv4 地址占用 16 个字节而不是 4 个字节
【发布时间】:2015-09-29 09:14:28
【问题描述】:

我正在尝试将域名解析为 ipv4 地址。

这是我正在做的最小代码

addrinfo hints, *results;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
int error = getaddrinfo("google.com", 0, &hints, &results);
for(addrinfo* info = results; info; info = info->ai_next)
{
    std::cout << (info->ai_family == AF_INET6 ? "ip6" : "ip4")
              << '[' << info->ai_addrlen << "]: ";
    for(uint i = 0; i < info->ai_addrlen; ++i)
        std::cout << int(((uint8_t*)info->ai_addr)[i]) << ' ';
    std::cout << std::endl;
}
freeaddrinfo(results);

当我运行它时,它会打印:

ip4[16]: 2 0 0 0 216 58 208 238 0 0 0 0 0 0 0 0 
ip4[16]: 2 0 0 0 216 58 208 238 0 0 0 0 0 0 0 0 
ip4[16]: 2 0 0 0 216 58 208 238 0 0 0 0 0 0 0 0

google.com的实际ip是216.58.208.238。所以出于某种原因,对于 ip v4,ai_addr 包含 16 个字节,实际上将地址存储在第 4 到第 8 个字节处。

我的问题是:其他 12 个字节是什么?

我阅读了the docs,并用谷歌搜索了一下,但在addr_len 上一无所获。另请注意,我没有设置AI_V4MAPPED 标志。

【问题讨论】:

标签: c++ linux dns ip


【解决方案1】:

我不确定这是否真的要求按照某些标准,但struct sockaddr 被定义为包含地址族的short,然后是地址族特定的 14 个字节数据。

用作地址的每种类型都必须与之兼容,因此至少具有相同的长度。

对于struct sockaddr_in(用于 IPv4 的那个),它看起来像这样:

struct sockaddr_in {
    short            sin_family;
    unsigned short   sin_port;
    struct in_addr   sin_addr;
    char             sin_zero[8];
};

地址族2个字节,端口2个字节,IPv4地址4个字节和8个字节填充以达到struct sockaddr的长度。

也就是说:您的问题有点错了,这不是 IPv4 地址(那只是 struct in_addr,实际上只有 4 个字节),而是 IPv4 的套接字地址。尽管如此,这里还是“浪费”了 8 个字节。

【讨论】:

  • POSIX 根据struct sockaddr 的要求定义了sa_familysa_data 字段,但仅指定sa_data 是一个可变长度字段(即C99 行话中的灵活数组)。所以sa_data 不需要有 14 个字节,但 Linux 选择这样做。 FreeBSD 做同样的事情,但它在struct sockaddr 的开头添加了一个额外的sa_len 字段。
  • 好评论,这就是我怀疑。所以“为什么”仍然是一个有效的问题,应该向首先为 Linux 设计struct sockaddr 的人提出。
猜你喜欢
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多