2015-07-10 137 views
2

我试图将一个域名解析为一个ipv4地址。为什么linux的IPv4地址需要16个字节而不是4个

下面是我在做

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,并在google上搜索了一下,但在addr_len上找不到任何东西。还请注意,我没有设置AI_V4MAPPED标志。

+1

我认为这是相关的:http://stackoverflow.com/questions/15608707/why-is-zero-padding-needed-in-sockaddr-in –

回答

3

我不知道这是否真的需要一些标准,但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个字节用于该端口,4个字节用于IPv4地址和8个字节的填充,以达到struct sockaddr的长度。

这就是说:你的问题是错了,这不是IPv4地址(这将只是struct in_addr这实际上只是4个字节)而是IPv4的套接字地址。但是,这里仍然有8个字节被“浪费”。

+1

POSIX根据需要定义了'sa_family'和'sa_data'字段在'struct sockaddr'中,但只指定'sa_data'是一个可变长度的字段(即C99术语中的一个灵活数组)。所以并不要求'sa_data'有14个字节,但Linux选择这样做。 FreeBSD也做同样的事情,但它在'struct sockaddr'的开头增加了一个'sa_len'字段。 –

+0

好评,这就是我*怀疑的*。因此,“为什么”仍然是一个有效的问题,应该首先针对Linux设计'struct sockaddr'。 –

相关问题