我是 C 和套接字编程的新手,仍然在 sockaddr_in
中苦苦挣扎结构体:
struct sockaddr_in {
short sin_family; /* Protocol family (always AF_INET) */
unsigned short sin_port; /* Port number in network byte order */
struct in_addr sin_addr; /* IP address in network byte order */
unsigned char sin_zero[8]; /* Pad to sizeof(struct sockaddr) */
};
和struct in_addr {
uint32_t s_addr; /* Address in network byte order (big-endian) */
};
我不确定是否需要 sin_zero
除了对齐要求,以下是我的假设,如果我错了,请纠正我:假设 1-自
sin_addr
ipv4地址是32位的,如果我们需要ipv6地址,sin_zero
的前4个字节将被分配并与 sin_addr
组合形成一个 64 位的 ipv6 地址。假设 2-如果我的假设是正确的,那么这就是我们需要指定套接字地址长度的原因,例如:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
是因为ipv6地址的可能性吗?所以如果使用 ipv4,那么 addrlen
应该是8,如果使用ipv6,那么addrlen
应该是12?
最佳答案
有多个协议(protocol)族。每个家族都有自己的地址结构。
示例:AF_INET
使用 sockaddr_in
, AF_INET6
使用 sockaddr_in6
, AF_UNIX
使用 sockaddr_un
等。但是 sockaddr
是基础结构。所有这些结构都必须类型转换为 sockaddr
在绑定(bind)/连接套接字时。int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
让我们看看sockaddr_in
的结构和 sockaddr
:
struct sockaddr_in {
short sin_family; /* Protocol family (always AF_INET) */
unsigned short sin_port; /* Port number in network byte order */
struct in_addr sin_addr; /* IP address in network byte order */
unsigned char sin_zero[8]; /* Pad to sizeof(struct sockaddr) */
};
struct in_addr {
uint32_t s_addr; /* Address in network byte order (big-endian) */
};
sockaddr
的结构是:struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
}
查看两个结构中元素的大小sockaddr_in
和 sockaddr
.两种结构中的第一个元素是相同的,并且占用相同的内存。
sin_port
--> 2 个字节sin_addr
--> 4 个字节sin_zero[8]
--> 8 个字节总计 = 14 个字节(等于
sa_data[14]
的大小)我们添加填充字节以使其结构大小相等。
引用:
https://man7.org/linux/man-pages/man2/bind.2.html
https://man7.org/linux/man-pages/man2/connect.2.html
关于c - sockaddr_in 的 pad 是做什么用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64255785/