sockaddr 中 sa_data 字段的用途是什么?
What is the purpose of the sa_data field in a sockaddr?
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
为地址参数传递的实际结构将取决于地址族。 sockaddr 结构定义如下:
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
因此对于 IPv4 地址 (AF_INET),将传递的实际结构是这样的:
/* Source http://linux.die.net/man/7/ip */
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
绑定代码是否读取 sockaddr.sa_family
值并根据它找到的值,然后将 sockaddr
结构转换为适当的结构,例如 sockaddr_in
?
为什么sa_data
设置为14个字符?如果我理解正确,sa_data
字段只是一个具有足够大内存 space 以适应所有地址族类型的字段?据推测,最初的设计者预计 14 个字符的宽度足以容纳所有未来类型。
根据 glibc manual:
The length 14 of sa_data is essentially arbitrary.
并且 FreeBSD developers handbook 提到了以下内容:
Please note the vagueness with which the sa_data field is declared,
just as an array of 14 bytes, with the comment hinting there can be
more than 14 of them.
This vagueness is quite deliberate. Sockets is a very powerful
interface. While most people perhaps think of it as nothing more than
the Internet interface—and most applications probably use it for that
nowadays—sockets can be used for just about any kind of interprocess
communications, of which the Internet (or, more precisely, IP) is only
one.
是的,sa_family
字段用于识别如何处理传递的结构(在绑定调用中转换为 struct sockaddr*
)。您也可以在 FreeBSD developers handbook.
中阅读更多有关它如何工作的信息
而实际上sockaddr
还有"polymorphic"(子)类型,其中sa_data
包含16个字节以上,例如:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
sockaddr
结构用作标记联合。通过读取 sa_family
字段,可以将其转换为适当形式的结构。
这14个字节是任意的。它大到足以容纳 IPv4 地址,但不足以容纳 IPv6 地址。还有一个 sockaddr_storage
结构,它对两者都足够大。阅读 SOCKADDR_STORAGE 上的 Microsoft 文档,它有 128 个字节,比 IPv6 所需的大得多。查了一些Linuxheaders,好像至少也有那么大。
作为参考,IPv6 结构是:
struct sockaddr_in6 {
u_int16_t sin6_family; // address family, AF_INET6
u_int16_t sin6_port; // port number, Network Byte Order
u_int32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
u_int32_t sin6_scope_id; // Scope ID
};
struct in6_addr {
unsigned char s6_addr[16]; // IPv6 address
};
如您所见,16 字节 s6_addr
字段本身已经大于 14 字节 sa_data
字段。 sa_family
字段后的总大小为 26 个字节。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
为地址参数传递的实际结构将取决于地址族。 sockaddr 结构定义如下:
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
因此对于 IPv4 地址 (AF_INET),将传递的实际结构是这样的:
/* Source http://linux.die.net/man/7/ip */
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
绑定代码是否读取 sockaddr.sa_family
值并根据它找到的值,然后将 sockaddr
结构转换为适当的结构,例如 sockaddr_in
?
为什么sa_data
设置为14个字符?如果我理解正确,sa_data
字段只是一个具有足够大内存 space 以适应所有地址族类型的字段?据推测,最初的设计者预计 14 个字符的宽度足以容纳所有未来类型。
根据 glibc manual:
The length 14 of sa_data is essentially arbitrary.
并且 FreeBSD developers handbook 提到了以下内容:
Please note the vagueness with which the sa_data field is declared, just as an array of 14 bytes, with the comment hinting there can be more than 14 of them.
This vagueness is quite deliberate. Sockets is a very powerful interface. While most people perhaps think of it as nothing more than the Internet interface—and most applications probably use it for that nowadays—sockets can be used for just about any kind of interprocess communications, of which the Internet (or, more precisely, IP) is only one.
是的,sa_family
字段用于识别如何处理传递的结构(在绑定调用中转换为 struct sockaddr*
)。您也可以在 FreeBSD developers handbook.
而实际上sockaddr
还有"polymorphic"(子)类型,其中sa_data
包含16个字节以上,例如:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
sockaddr
结构用作标记联合。通过读取 sa_family
字段,可以将其转换为适当形式的结构。
这14个字节是任意的。它大到足以容纳 IPv4 地址,但不足以容纳 IPv6 地址。还有一个 sockaddr_storage
结构,它对两者都足够大。阅读 SOCKADDR_STORAGE 上的 Microsoft 文档,它有 128 个字节,比 IPv6 所需的大得多。查了一些Linuxheaders,好像至少也有那么大。
作为参考,IPv6 结构是:
struct sockaddr_in6 {
u_int16_t sin6_family; // address family, AF_INET6
u_int16_t sin6_port; // port number, Network Byte Order
u_int32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
u_int32_t sin6_scope_id; // Scope ID
};
struct in6_addr {
unsigned char s6_addr[16]; // IPv6 address
};
如您所见,16 字节 s6_addr
字段本身已经大于 14 字节 sa_data
字段。 sa_family
字段后的总大小为 26 个字节。