为什么sockaddr_in需要零填充?

lou*_*xiu 13 c linux kernel

我用谷歌搜索了一些人说"要与struct sockaddr保持相同的大小".但内核不会直接使用sockaddr(对吧?).使用时.内核会把它重新归结为它.那么为什么需要零填充?

struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
};

struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};

struct in_addr {
    unsigned long s_addr;          // load with inet_pton()
};
Run Code Online (Sandbox Code Playgroud)

Rin*_*g Ø 11

我能找到的两个更相关的信息是

谈论一段清除字节的代码片段

这是一个错误.我发现偶尔会发生这种情况.此错误可能导致应用程序中的未定义行为.

随后进行了一些解释

大多数网络代码不使用sockaddr_in,它使用sockaddr.当您使用像sendto这样的函数时,您必须显式地将sockaddr_in或您使用的任何地址转换为sockaddr.sockaddr_in与sockaddr的大小相同,但内部大小相同,因为有轻微的黑客攻击.

那个黑客是sin_zero.实际上sockaddr_in中有用数据的长度比sockaddr短.但是使用一个小缓冲区在sockaddr_in中填充差异; 缓冲区是sin_zero.

最后,可以在各个地方找到的信息

在某些架构上,它不会导致任何不清除sin_zero的问题.但在其他架构上它可能会.规范要求清除sin_zero,所以如果你想让你的代码现在和未来都没有bug,你必须这样做.

回答这个问题

为什么我们需要这个8字节填充?

和答案

Unix网络编程第3.2章说,"POSIX规范只需要结构中的三个成员:sin_family,sin_addr和sin_port.符合POSIX的实现可以定义其他结构成员,这对于Internet套接字是正常的地址结构.几乎所有实现都添加了sin_zero成员,以便所有套接字地址结构的大小至少为16个字节."

它有点像结构填充,可能在将来保留给额外的字段.您将永远不会使用它,就像评论一样.

这与第一个链接一致.清除字节告诉接收者"我们这边没有使用那些字节".