sockaddr和sockaddr_存储之间的差异

sockaddr和sockaddr_存储之间的差异,c,sockets,C,Sockets,sockaddr和sockaddr_存储之间的区别是什么?我不明白,因为看代码,它们看起来完全一样: 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]; } 存储变体意味

sockaddr和sockaddr_存储之间的区别是什么?我不明白,因为看代码,它们看起来完全一样:

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];
}

存储
变体意味着“尽可能大”,并且也可以正确对齐(因此它可以保存IPv6地址、IPv4地址、ISO协议地址,甚至是
AF_UNIX
路径名或其他任何内容)。把它想象成一个大得足以容纳“任何套接字地址”的箱子/桶/面包盒/(其他最喜欢的存储项目),不管它是什么类型的套接字地址。IPv4地址(
struct sockaddr\u in
)很小,显然无法在其中保存IPv6地址,但
struct sockaddr\u存储
有一个很大的空间

原始的
struct sockaddr
可能应该有这么大,但不是。所以这基本上是一个解决历史错误的方法


(您上面引用的版本中没有对齐项,这似乎是可疑的。)

,§3.10-可移植性添加。但是如果
struct sockaddr
可以包含
struct sockaddr\u in6
为什么我需要
struct sockaddr\u存储
?它不能(包含
sockaddr\u in6
)。旧的
sockaddr
是16个字节,6中的
struct sockaddr\u是32个字节。在我见过/使用过的系统上,
存储
版本的长度为128字节。@torek但是我知道的所有套接字函数都需要一个指向
sockaddr
的指针作为参数,而不是
sockaddr\u存储*
?@DarthMoon:是的。这有点像是一个历史性的错误:他们可能应该采取
void*
。如果您使用的是inet(不是inet 6)连接,则需要
中实际的
sockaddr\u的实际地址。如果使用inet6连接,则需要实际
sockadder\u in6
的实际地址。如果您使用的是unix域连接,则需要实际的
sockaddr\u un
的实际地址。如果您编写的库需要为其他人提供空间来插入其中任何一个库,那么您需要提供一个实际的sockaddr_存储。