Winsock Address Family Specific Structures
This section details the structures used by Windows Sockets (Winsock) to represent network addresses for various address families, such as IPv4 and IPv6. Understanding these structures is crucial for developing network-aware applications.
Overview
Winsock uses a set of structures to store and manipulate network address information. The specific structure used depends on the address family of the socket. The most common address families are:
AF_INET
: For IPv4 addresses.AF_INET6
: For IPv6 addresses.AF_UNSPEC
: An unspecified address family.
The primary structure for handling addresses in Winsock is the SOCKADDR
structure, which is a generic structure. For specific address families, more specialized structures are used, such as SOCKADDR_IN
for IPv4 and SOCKADDR_IN6
for IPv6. These specialized structures are often cast to SOCKADDR*
when passed to Winsock functions.
SOCKADDR_IN
(IPv4)
The SOCKADDR_IN
structure is used to specify an IPv4 endpoint address. It contains the address family, port number, and the IPv4 address itself.
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;
typedef struct sockaddr_in {
short int sin_family; // Address family (AF_INET)
u_short sin_port; // Port number
struct in_addr sin_addr; // IPv4 address
char sin_zero[8]; // Reserved for future use
} SOCKADDR_IN, *PSOCKADDR_IN;
Members:
sin_family
: Must be set toAF_INET
.sin_port
: The port number on which to bind or connect. This should be in network byte order (usehtons()
).sin_addr
: AnIN_ADDR
structure containing the IPv4 address. TheS_addr
member holds the address in network byte order.sin_zero
: A padding field, typically set to zeros.
SOCKADDR_IN6
(IPv6)
The SOCKADDR_IN6
structure is used to specify an IPv6 endpoint address. It's more complex than SOCKADDR_IN
due to the larger size of IPv6 addresses.
typedef struct in6_addr {
union {
u_char u8[16];
u_short u16[8];
u_long u32[4];
} u;
} IN6_ADDR, *PIN6_ADDR;
typedef struct sockaddr_in6 {
short int sin6_family; // Address family (AF_INET6)
u_short sin6_port; // Port number
u_long sin6_flowinfo; // Flow information
struct in6_addr sin6_addr; // IPv6 address
u_long sin6_scope_id; // Scope identifier
} SOCKADDR_IN6, *PSOCKADDR_IN6;
Members:
sin6_family
: Must be set toAF_INET6
.sin6_port
: The port number in network byte order (usehtons()
).sin6_flowinfo
: Flow information for the IPv6 packet.sin6_addr
: AnIN6_ADDR
structure containing the 128-bit IPv6 address.sin6_scope_id
: The scope identifier for link-local addresses.
SOCKADDR
(Generic)
The SOCKADDR
structure is a generic structure that can hold addresses of any family. It is often used as a common type when passing address information to Winsock functions, where the actual structure type is determined by the sa_family
field.
typedef struct sockaddr {
u_short sa_family; // Address family (e.g., AF_INET, AF_INET6)
char sa_data[14]; // Socket address (variable length)
} SOCKADDR, *PSOCKADDR;
When using SOCKADDR
, you typically cast it to the appropriate specific structure (SOCKADDR_IN*
or SOCKADDR_IN6*
) after checking the sa_family
field to access the correct members.
Related Structures
Beyond the primary address structures, Winsock defines other related structures:
Structure Name | Description |
---|---|
IN_PKTINFO |
Provides information about an IPv4 packet, including the interface and destination address. |
IN6_PKTINFO |
Provides information about an IPv6 packet, including the interface and destination address. |
WSAPOLLFD |
Used with the WSAPoll function to describe sockets to monitor for events. |
Byte Ordering
It's important to remember that network protocols use a specific byte order (big-endian, also known as network byte order). Winsock functions that deal with port numbers and IP addresses often require these values to be in network byte order. Use the following functions to convert between host byte order and network byte order:
htons()
: Host to network short.htonl()
: Host to network long.ntohs()
: Network to host short.ntohl()
: Network to host long.
For example, when setting the sin_port
or sin6_port
fields, you should always call htons()
on the port number.