sockaddr_in結構體定義 ``` struct sockaddr_in { sa_family_t sin_family; //地址族(Address Family) uint16_t sin_port; //16位TCP/UDP端口號 struct in_addr sin_add; //32位IP地址 char sin_zero[8]; //不使用 };
struct in_addr
{
In_addr_t s_addr; //32位IPv4地址
};
####1.成員sin_family
地址族(Address Family) | 含義
- | :-:
AF_INET | IPv4網絡協議中使用的地址族
AF_INET6| IPv6網絡協議中使用的地址族
AF_LOCAL | 本地通信中采用的Unix協議的地址族
####2.成員sin_port
該成員保存16位端口號,重點在於,他以網絡字節序保存。
####3.成員sin_addr
該成員保存32位IP地址信息,且也以網絡字節序保存。
####4.成員sin_zero
無特殊含義。只是為了使結構體sockaddr_in的大小與sockaddr結構體保持一致而插入的成員。必須填充為0,否則無法得到想要的結果。
下面給出sockaddr_in結構體傳遞給bind()函數的代碼
struct sockaddr_in serv_addr
....
if( bind(serv_sock, (struct sockaddr *) &serv_addr), sizeof(serv_addr) == -1 )
//錯誤處理
....
請注意第二個參數將sockaddr_in類型轉換為sockaddr類型。因為bind()函數需要一個sockaddr類型的參數,但是直接向sockaddr結構體填充地址族、端口號、IP地址等信息不太容易,而填充sockaddr_in類型結構體則容易得多,故先填充sockaddr_in再將其轉換為sockaddr類型。
下面給出sockaddr結構體定義。
struct sockaddr
{
sa_family_t sin_family; //地址族(Address Family)
char sa_data[14]; //地址信息
}
此結構體成員sa_data保存的地址信息中需包含IP地址和端口號,剩余部分應填充0,這也是bind()函數要求的。而這對於包含地址信息來講非常麻煩,繼而就有了結構體sockaddr_in。若按照之前講解的填寫好sockaddr_in結構體,則將生產負荷bind()函數要求的字節流。最后轉換為sockaddr類型的結構體變量,再傳遞給bind()函數即可。
會不會有這樣的疑問,sockaddr_in是保存IPv4地址信息的結構體,那為何還需要通過sin_family單獨指定地址族信息呢?這與sockaddr結構體有關。結構體sockaddr並非只為IPv4設計的。這從保存地址信息的數組sa_data長度為14字節也可看出。因此,結構體sockaddr要求在sin_family中指定地址族信息。為了與sockaddr保持一致,sockaddr_in結構體中也有地址族信息。