sockaddr和sockaddr_存储之间的差异
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]; } 存储变体意味
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_存储。