当您向sockaddr
发送一个指向struct sockaddr_storage
的指针时,希望指向struct sockaddr
的函数可能会将您发送到sockaddr
的指针类型化。通过这种方式,他们访问它就好像它是一个struct sockaddr
。
struct sockaddr_storage
被设计以适应既是struct sockaddr_in
和struct sockaddr_in6
你没有创建自己的struct sockaddr
,你通常会创建取决于你使用的IP版本struct sockaddr_in
或struct sockaddr_in6
。为了避免试图知道你将使用什么IP版本,你可以使用一个struct sockaddr_storage
,它可以保存。这将通过connect(),bind()等功能被转换为struct sockaddr
,并以这种方式进行访问。
你可以看到以下这些结构的(填充是实现特定的,为了对准):
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
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
};
struct sockaddr_in6 {
u_int16_t sin6_family; // address family, AF_INET6
u_int16_t sin6_port; // port number, Network Byte Order
u_int32_t sin6_flowinfo; // IPv6 flow information
struct in6_addr sin6_addr; // IPv6 address
u_int32_t sin6_scope_id; // Scope ID
};
struct sockaddr_storage {
sa_family_t ss_family; // address family
// all this is padding, implementation specific, ignore it:
char __ss_pad1[_SS_PAD1SIZE];
int64_t __ss_align;
char __ss_pad2[_SS_PAD2SIZE];
};
所以你可以看到,如果函数需要一个IPv4地址,它只会读前4个字节(因为它假定结构类型为struct sockaddr
,否则它将读取IPv6的全部16个字节)。
因此,假设我有一个指向'struct sockaddr_storage'的指针,名为'sas',并且结构中的所有字段都已正确地填充了地址和地址系列。我现在执行这个:'struct sockaddr * s =(struct sockaddr *)sas'。我现在怎样才能把地址从's'中取出? –
你不会直接使用'struct sockaddr'。你要做的就是将它转换回'sockaddr_storage'或'sockaddr_in',然后读取它。正如你可以从我的帖子看到'sockaddr'有足够的空间来适应IPv4或v6地址。话虽如此,我不知道为什么你会想为'struct sockaddr'强制转换为除了函数需要的参数之外的任何东西。 'struct sockaddr'不适用于'程序员使用'。 – theprole
我正在读一本书,说sockaddr不够大,无法容纳sockaddr_in6。 –