Why can we cast sockaddr to sockaddr_in
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
.
Jean-Luc
I am a electronic/communications engineering student with interests in C++, Ruby, Python and assembler programming. I also love LaTeX and Gnuplot.
Updated on June 05, 2022Comments
-
Jean-Luc almost 2 years
I can see why it is useful to cast
sockaddr
tosockaddr_in
, but I don't understand how this is possible. From what I've read, they're the same size andsockaddr_in
is added withsin_zero
to make it the same size. I would like to know how the compiler knows where to get the information fromsockaddr_in
if it is layed out differently tosockaddr
. -
Jean-Luc about 12 yearsIt seems odd because the variable that is supposed to store the address in sockaddr is sa_data which is char[14], yet sockaddr_in uses an unsigned short. I'm assuming that the compiler would read the first unsigned short number of bytes from the char[14] and make that the address, and the rest of char[14] is the data to be sent? Also, if I add the sizes of the two structs, they don't appear to be the same size. sin_zero seems too big. I'm just tring to get what's going on here!
-
Remy Lebeau about 12 yearsA
sockaddr
is 16 bytes in size - the first two bytes are thesa_family
, and the remaining 14 bytes are thesa_data
which is arbitrary data. Asockaddr_in
is also 16 bytes in size - the first 2 bytes are thesin_family
(alwaysAF_INET
), the next 2 bytes are thesin_port
, the next 4 bytes are thesin_addr
(IP address), and the last 8 bytes are thesin_zero
which is unused in IPv4 and provided only to ensure 16 bytes. This way, you can look atsockaddr.sa_family
first, and if it isAF_INET
then interpret the entiresockaddr
as asockaddr_in
. -
Remy Lebeau about 12 yearsA
sockaddr_in
is not stored inside ofsockaddr.sa_data
field. The entiresockaddr
is the entiresockaddr_in
(whensockaddr.sa_family
isAF_INET
, that is). If you take asockaddr*
pointer and cast it to asockaddr_in*
pointer,sockaddr.sa_family
issockaddr_in.sin_family
, bytes 0-1 ofsockaddr.sa_data
aresockaddr_in.sin_port
, bytes 2-5 aresockaddr_in.sin_addr
, and bytes 6-13 aresockaddr_in.sin_zero
. -
Michael Heidelberg over 8 years@RemyLebeau: I hope you can edit your post and add the useful content of the comments inside ( especially the second comment that treats how the struct fields are interpreted ) It'll be more clear and more specific.
-
Roman R. over 8 years@MichaelHeidelberg: No problem, I did it.
-
Michael Heidelberg over 8 years@RemyLebeau: Great! Thank you, that's well explained.
-
Armen Michaeli over 7 yearsHow does sturct padding figure into this? What gives guarantees that the two structs have similar alignment between their members in so far pointer to one can be used in place of pointer to another?
-
Roman R. over 7 years@amn: Have a look at declarations side by side. You will see how the fields are defined similarly in the beginning and map one to one perfectly, then different declarations are different interpretations of the same data (in case of casting). The structures are defined in the way that guarantees accurate mapping.
-
U. Windl about 3 yearsI think the real question is: Is it guaranteed that
sizeof(struct sockaddr) == sizeof(struct sockaddr_in)
(and other address families likesizeof(struct sockaddr) == sizeof(struct sockaddr_in6)
)?