struct sockaddr { // generic socket
unsigned short sa_family; // protocol family for socket
char sa_data[14];
// address data (and defines full size to be 16 bytes)
};
sockaddr_in
is used to model IPv4 address/port pairs.
sin_family
field should always be initialized to be AF_INET
, which is a constant used to be clear that IPv4 addresses are being used. If it feels redundant that a record dedicated to IPv4 needs to store a constant saying everything is IPv4, then stay tuned.sin_port
field stores a port number in network byte (i.e. big endian) order.sockaddr_in
field stores an IPv4 address as a packed, big endian int
, as you saw with gethostbyname
and the struct hostent
.sin_zero
field is generally ignored (though it's often set to store all zeroes). It exists primarily to pad the record up to 16 bytes.struct sockaddr_in { // IPv4 socket address record
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
struct sockaddr_in6 { // IPv6 socket address record
unsigned short sin6_family;
unsigned short sin6_port;
unsigned int sin6_flowinfo;;
struct in6_addr sin6_addr;
unsigned int sin6_scope_id;
};
sockaddr_in6
is used to model IPv6 address/port pairs.
sin6_family
field should always be set to AF_INET6
. As with the sin_family
field, sin6_family
field occupies the first two bytes of surrounding record.sin6_port
field holds a two-byte, network-byte-ordered port number, just like sin_port does.struct in6_addr
is also wedged in there to manage a 128-bit IPv6 address.sin6_flowinfo
and sin6_scope_id
are beyond the scope of what we need, so we'll ignore them.struct sockaddr { // generic socket
unsigned short sa_family; // protocol family for socket
char sa_data[14];
// address data (and defines full size to be 16 bytes)
};
struct sockaddr_in { // IPv4 socket address record
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
struct sockaddr_in6 { // IPv6 socket address record
unsigned short sin6_family;
unsigned short sin6_port;
unsigned int sin6_flowinfo;;
struct in6_addr sin6_addr;
unsigned int sin6_scope_id;
};
struct sockaddr
is the best C can do to emulate an abstract base class.
struct sockaddr
, but many system calls will accept parameters of type struct sockaddr *
.struct sockaddr_in
or a struct sockaddr_in6
. The system call relies on the value within the first two bytes—the sa_family
field—to determine what the true record type is.struct sockaddr { // generic socket
unsigned short sa_family; // protocol family for socket
char sa_data[14];
// address data (and defines full size to be 16 bytes)
};
struct sockaddr_in { // IPv4 socket address record
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
struct sockaddr_in6 { // IPv6 socket address record
unsigned short sin6_family;
unsigned short sin6_port;
unsigned int sin6_flowinfo;;
struct in6_addr sin6_addr;
unsigned int sin6_scope_id;
};