sockaddr和sockaddr_storage的区别

w8ntj3qf  于 2024-01-06  发布在  其他
关注(0)|答案(2)|浏览(134)

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

字符串

iq3niunx

iq3niunx1#

storage变体的意思是“尽可能大”,并且也要正确对齐(所以它可以保存IPv6地址,或IPv4地址,或ISO协议地址,甚至是AF_UNIX路径名或其他)。(另一个最喜欢的存储项目),大到足以容纳“任何套接字地址”,IPv4地址(struct sockaddr_in)很小,显然不能容纳IPv6地址,但struct sockaddr_storage有一个很大的空间。
最初的struct sockaddr可能 * 应该 * 这么大,但不是。所以这基本上是一个历史错误的解决方案。
(The您上面引用的版本中没有对齐项,这似乎是可疑的。)

n7taea2i

n7taea2i2#

最初在套接字编程中有一个SOCKADDR(套接字地址)-协议无关的blob,表示 “一个地址”。它可以是一个IPX地址,一个IPv4地址,一个AppleTalk地址,等等。

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

但是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
所以所有的头文件都应该被修改:

--- int connect(int sockfd, const struct sockaddr         *addr, socklen_t addrlen);
+++ int connect(int sockfd, const struct sockaddr_storage *addr, socklen_t addrlen);


希望128个字节足够了,我们再也不用经历这个了。

相关问题