當您向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。 –