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
.
问题:
回答1:
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:
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
.
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_family
issockaddr_in.sin_family
- bytes 0-1 of
sockaddr.sa_data
aresockaddr_in.sin_port
- bytes 2-5 are
sockaddr_in.sin_addr
- bytes 6-13 are
sockaddr_in.sin_zero
.