为什么我们可以将 sockaddr 转换为 sockaddr_in我们可以、转换为、sockaddr、sockaddr_in

2023-09-07 13:13:18 作者:持之以恒

我明白为什么将 sockaddr 转换为 sockaddr_in 很有用,但我不明白这怎么可能.根据我的阅读,它们的大小相同,并且 sockaddr_in 添加了 sin_zero 以使其大小相同.如果与 sockaddr 的布局不同,我想知道编译器如何知道从 sockaddr_in 获取信息的位置.

I can see why it is useful to cast sockaddr to sockaddr_in, but I don't understand how this is possible. From what I've read, they're the same size and sockaddr_in is added with sin_zero to make it the same size. I would like to know how the compiler knows where to get the information from sockaddr_in if it is layed out differently to sockaddr.

推荐答案

这是可能的,因为您通常转换指针,而不是结构本身.您执行自然语言中的意思是请将此指向 socket 结构 的指针视为指向 internet socket 结构 的指针".编译器重新解释指针没有问题.

It is possible because you normally cast pointers, not the structures themselves. You do what in natural language means "please treat this pointer to a socket structure as a pointer to an internet socket structure instead". Compiler has no problems to re-interpret the pointer.

这里是从评论中获得的更详细的描述:

Here is more detailed description taken up from comments:

sockaddr 大小为 16 个字节 - 前两个字节是 sa_family,其余 14 个字节是 sa_data,即任意数据.sockaddr_in 的大小也是 16 字节 - 前 2 个字节是 sin_family(总是 AF_INET),接下来的 2 个字节是 sin_port,接下来的 4 个字节是 sin_addr(IP 地址),最后 8 个字节是 sin_zero,在 IPv4 中未使用,仅提供给确保 16 个字节.这样就可以先看sockaddr.sa_family,如果是AF_INET则将整个sockaddr解释为sockaddr_in.

A sockaddr is 16 bytes in size - the first two bytes are the sa_family, and the remaining 14 bytes are the sa_data which is arbitrary data. A sockaddr_in is also 16 bytes in size - the first 2 bytes are the sin_family (always AF_INET), the next 2 bytes are the sin_port, the next 4 bytes are the sin_addr (IP address), and the last 8 bytes are the sin_zero which is unused in IPv4 and provided only to ensure 16 bytes. This way, you can look at sockaddr.sa_family first, and if it is AF_INET then interpret the entire sockaddr as a sockaddr_in.

sockaddr_in 不存储在 sockaddr.sa_data 字段内.整个sockaddr就是整个sockaddr_in(当sockaddr.sa_family就是AF_INET时).如果您将 sockaddr* 指针转换为 sockaddr_in* 指针,则:

A sockaddr_in is not stored inside of sockaddr.sa_data field. The entire sockaddr is the entire sockaddr_in (when sockaddr.sa_family is AF_INET, that is). If you take a sockaddr* pointer and cast it to a sockaddr_in* pointer, then:

sockaddr.sa_familysockaddr_in.sin_familysockaddr.sa_data 的字节 0-1 是 sockaddr_in.sin_port字节 2-5 是 sockaddr_in.sin_addr字节 6-13 是 sockaddr_in.sin_zero. sockaddr.sa_family is sockaddr_in.sin_family bytes 0-1 of sockaddr.sa_data are sockaddr_in.sin_port bytes 2-5 are sockaddr_in.sin_addr bytes 6-13 are sockaddr_in.sin_zero.