sockaddr和sockaddr_storage之间的区别

9

sockaddr和sockaddr_storage有何区别?我不理解,因为在代码中它们看起来很相似:

struct sockaddr {
    uint8_t sa_len;
    sa_family_t sa_family;
    char sa_data[14];
}

struct sockaddr_storage {
    uint8_t ss_len;
    sa_family_t ss_family;
    char ss_padding[SIZE];
}
1个回答

15

storage 变体旨在“尽可能大”,并且正确对齐(因此可以容纳IPv6地址、IPv4地址、ISO协议地址,甚至是 AF_UNIX 路径名或其他任何类型的套接字地址)。将其视为一个足够大,可以容纳“任何套接字地址”的储物箱/桶子/面包盒(或其他您喜欢的存储物品)。IPv4地址(struct sockaddr_in)很小,显然无法在其中容纳IPv6地址,但是 struct sockaddr_storage 有一个宽敞的货舱。

原始的 struct sockaddr 可能本应该如此大,但实际上不是。因此,这基本上是对历史错误的一种解决方法。

(您引用的版本中没有对齐项,这似乎令人怀疑。)


RFC-2553RFC-3493 §3.10 - 可移植性增强。 - Anya Shenanigans
但是如果一个 struct sockaddr 可以包含一个 struct sockaddr_in6,那么我为什么需要一个 struct sockaddr_storage - zer0uno
3
它无法包含一个 sockaddr_in6。旧的 sockaddr 是16个字节,而一个 struct sockaddr_in6 是32个字节。在我看到/使用的系统上,storage 版本长度为128个字节。 - torek
1
@torek 但是我知道的所有套接字函数都需要一个指向sockaddr的指针作为参数,而不是sockaddr_storage* - user10251509
2
@DarthMoon:是的。这有点历史上的错误:他们可能应该采用void *。如果您正在使用inet(而不是inet6)连接,则需要实际的sockaddr_in地址。如果您正在使用inet6连接,则需要实际的sockadder_in6地址。如果您正在使用unix域连接,则需要实际的sockaddr_un地址。如果您正在编写一个需要为其他人提供空间以将其中任何一个推入的库,则需要提供实际的sockaddr_storage。 - torek
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接