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]; }
字符串
iq3niunx1#
storage变体的意思是“尽可能大”,并且也要正确对齐(所以它可以保存IPv6地址,或IPv4地址,或ISO协议地址,甚至是AF_UNIX路径名或其他)。(另一个最喜欢的存储项目),大到足以容纳“任何套接字地址”,IPv4地址(struct sockaddr_in)很小,显然不能容纳IPv6地址,但struct sockaddr_storage有一个很大的空间。最初的struct sockaddr可能 * 应该 * 这么大,但不是。所以这基本上是一个历史错误的解决方案。(The您上面引用的版本中没有对齐项,这似乎是可疑的。)
storage
AF_UNIX
struct sockaddr_in
struct sockaddr_storage
struct sockaddr
n7taea2i2#
最初在套接字编程中有一个SOCKADDR(套接字地址)-协议无关的blob,表示 “一个地址”。它可以是一个IPX地址,一个IPv4地址,一个AppleTalk地址,等等。
SOCKADDR
SOCKADDR (16-bytes) SOCKADDR_IN (16-bytes) (Protocol agnostic) (SOCKADDR for IPv4) +---------------------+ +-----------------------+ | sa_family (2-bytes) | | sin_family (2-bytes) | |---------------------| |-----------------------| | sa_data (14-bytes) | | sin_port (2-bytes) | | | | S_addr (4-bytes) | | | | | | | | sin_zero (8-bytes) | | | | | | | | | | | | | +---------------------+ +-----------------------+
字符串最初的希望是16字节的SOCKADDR结构足够大,可以处理任何现有或将来的协议,这意味着SOCKADDR将是协议无关的。
但是IPv6的16字节(128位)地址出现了沿着。突然之间,SOCKADDR结构的14字节有效载荷不够大(如果减去端口号的2字节,则为12字节):
SOCKADDR (16-bytes) SOCKADDR_IN (16-bytes) SOCKADDR_IN6 (24-bytes) (Protocol agnostic) (SOCKADDR for IPv4) (SOCKADDR for IPv6) +---------------------+ +-----------------------+ +-------------------------+ | sa_family (2-bytes) | | sin_family (2-bytes) | | sin6_family (2-bytes) | |---------------------| |-----------------------| |-------------------------| | sa_data (14-bytes) | | sin_port (2-bytes) | | sin6_port (2-bytes) | | | | S_addr (4-bytes) | | sin6_flowinfo (4-bytes) | | | | | | | | | | sin_zero (8-bytes) | | IN6_ADDR (16 bytes) | | | | | | | | | | | | | | | | | | | +---------------------+ +-----------------------+ | | | | | | | | +-------------------------+
型因此,创建了一个新的协议无关的 * 套接字地址 * 结构:SOCKADDR → SOCKADDR_
SOCKADDR_STORAGE (128-bytes) SOCKADDR_IN (16-bytes) SOCKADDR_IN6 (24-bytes) (protcol agnostic) (IPv4) (IPv6) +---------------------+ +-----------------------+ +-------------------------+ | ss_family (2-bytes) | | sin_family (2-bytes) | | sin6_family (2-bytes) | |---------------------| |-----------------------| |-------------------------| | ss_pad (126-bytes) | | sin_port (2-bytes) | | sin6_port (2-bytes) | | | | S_addr (4-bytes) | | sin6_flowinfo (4-bytes) | | | | | | | | | | sin_zero (8-bytes) | | IN6_ADDR (16 bytes) | | | | | | | | | | | | | | | | | | | | | +-----------------------+ | | | | | | | | | | | | | | | | +-------------------------+ | | | | | | ..................... | | | | | | | | +---------------------+
型因此,我们的目标是让每个人都停止使用SOCKADDR(在协议不可知结构上的失败尝试),将所有引用替换为SOCKADDR_STORAGE。所以所有的头文件都应该被修改:
SOCKADDR_STORAGE
--- int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +++ int connect(int sockfd, const struct sockaddr_storage *addr, socklen_t addrlen);
型希望128个字节足够了,我们再也不用经历这个了。
2条答案
按热度按时间iq3niunx1#
storage
变体的意思是“尽可能大”,并且也要正确对齐(所以它可以保存IPv6地址,或IPv4地址,或ISO协议地址,甚至是AF_UNIX
路径名或其他)。(另一个最喜欢的存储项目),大到足以容纳“任何套接字地址”,IPv4地址(struct sockaddr_in
)很小,显然不能容纳IPv6地址,但struct sockaddr_storage
有一个很大的空间。最初的
struct sockaddr
可能 * 应该 * 这么大,但不是。所以这基本上是一个历史错误的解决方案。(The您上面引用的版本中没有对齐项,这似乎是可疑的。)
n7taea2i2#
最初在套接字编程中有一个
SOCKADDR
(套接字地址)-协议无关的blob,表示 “一个地址”。它可以是一个IPX地址,一个IPv4地址,一个AppleTalk地址,等等。字符串
最初的希望是16字节的
SOCKADDR
结构足够大,可以处理任何现有或将来的协议,这意味着SOCKADDR
将是协议无关的。但是IPv6
但是IPv6的16字节(128位)地址出现了沿着。突然之间,
SOCKADDR
结构的14字节有效载荷不够大(如果减去端口号的2字节,则为12字节):型
因此,创建了一个新的协议无关的 * 套接字地址 * 结构:
SOCKADDR → SOCKADDR_
型
因此,我们的目标是让每个人都停止使用
SOCKADDR
(在协议不可知结构上的失败尝试),将所有引用替换为
SOCKADDR_STORAGE
。所以所有的头文件都应该被修改:
型
希望128个字节足够了,我们再也不用经历这个了。