- The three data structures presented below are in place to model the IP address/port pairs:
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)
};
The
sockaddr_in
is used to model IPv4 address/port pairs.
- The
sin_family
field should always be initialized to beAF_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. - The
sin_port
field stores a port number in network byte (i.e. big endian) order. - The
sockaddr_in
field stores an IPv4 address as a packed, big endianint
, as you saw withgethostbyname
and thestruct hostent
. - The
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;
};
The sockaddr family
- The three data structures presented below are in place to model the IP address/port pairs:
The
sockaddr_in6
is used to model IPv6 address/port pairs.
- The
sin6_family
field should always be set toAF_INET6
. As with thesin_family
field,sin6_family
field occupies the first two bytes of surrounding record. - The
sin6_port
field holds a two-byte, network-byte-ordered port number, just like sin_port does. - A
struct in6_addr
is also wedged in there to manage a 128-bit IPv6 address. -
sin6_flowinfo
andsin6_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;
};
The sockaddr family
- The three data structures presented below are in place to model the IP address/port pairs:
The
struct sockaddr
is the best C can do to emulate an abstract base class.
- You rarely if ever declare variables of type
struct sockaddr
, but many system calls will accept parameters of typestruct sockaddr *
. - Rather than define a set of network system calls for IPv4 addresses and a second set of system calls for IPv6 addresses, Linux defines one set for both.
- If a system call accepts a parameter of type struct sockaddr *, it really accepts the address of either a
struct sockaddr_in
or astruct sockaddr_in6
. The system call relies on the value within the first two bytes—thesa_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;
};
The sockaddr family
sockaddr
By Chris Gregg
sockaddr
- 1,610