Why is sin_addr inside the structure in_addr?
My doubt is related to the following structure of sockets in UNIX :
struct sockaddr_in {
short sin_family; // e.g. AF_INET, AF_INET6
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
Here the member sin_addr
is of type struct in_addr
.
But I don't get why someone would like to do that as all struct inaddr
has is :
struct in_addr {
unsigned long s_addr; // load with inet_pton()
};
All in_addr
has is just one member s_addr
. Why cannot we have something like this :
struct sockaddr_in {
short sin_family; // e.g. AF_INET, AF_INET6
unsigned short sin_port; // e.g. htons(3490)
unsigned long s_addr ;
char sin_zero[8]; // zero this if you want to
};
Solution 1:
struct in_addr
is sometimes very different than that, depending on what system you're on. On Windows for example:
typedef struct in_addr {
union {
struct {
u_char s_b1,s_b2,s_b3,s_b4;
} S_un_b;
struct {
u_short s_w1,s_w2;
} S_un_w;
u_long S_addr;
} S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;
The only requirement is that it contain a member s_addr
.
Solution 2:
Because the in_addr
structure may contain more than one member.
http://pubs.opengroup.org/onlinepubs/009604599/basedefs/netinet/in.h.html
Solution 3:
struct in_addr
is a more than just an integer is because it might have more than in_addr_t
. In many systems, it has a union
, and the reason of such implementation is for class A/B/C addresses, which are not used now.
Unix Network Programming Volume 1 explains the historical reason in detail:
The reason the
sin_addr
member is a structure, and not just anin_addr_t
, is historical. Earlier releases (4.2BSD) defined thein_addr
structure as aunion
of various structures, to allow access to each of the 4 bytes and to both of the 16-bit values contained within the 32-bit IPv4 address. This was used with class A, B, and C addresses to fetch the appropriate bytes of the address. But with the advent of subnetting and then the disappearance of the various address classes with classless addressing, the need for the union disappeared. Most systems today have done away with theunion
and just definein_addr
as a structure with a singlein_addr_t
member.