各位看官們,大家好,上一回中咱們說的是socket通信地址系統調用的例子,這一回咱們繼續說該例子。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
看官們,我們在上一回介紹的通信地址系統調用有效地解決了數據存儲方式的問題,不過,還有一個系統調用也可以解決這種問題,這一回我們將介紹該系統調用:getaddrinfo。
該系統調用從其名字上看是用來獲取地址的信息,這裡的地址主要指套接字通信地址。它獲取到的地址信息不需要進行字節序轉換,我們可以直接用來進行套接字通信。不過,我們不能只看名字就給它下結論,除了可以獲取套接字地址信息外,它還可以獲取獲取套接字的屬性(域、類型和協議)以及其它與通信相關的信息。下面是該系統調用的函數原型:
int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
在介紹該函數前,我們先介紹一下該函數中使用到的一個類型: struct addrinfo,它的定義如下所示:
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
該類型屬於結構體類型,它擁有八個成員,我們依次介紹這些成員:
成員ai_flags用來控制 getaddrinfo的行為,主要用在getaddrinfo函數中的hints參數中; 成員ai_family表示套接字的域; 成員ai_socktype表示套接字的類型; 成員ai_protocol表示套接字通信時使用的協議; 成員ai_addrlen表示套接字地址的長度; 成員ai_addr是一個指針,它指向套接字的地址; 成員ai_canonname是一個指針,它指向本地主機的名字; 成員ai_next是一個指針,它指向一個鏈表,鏈表中存放著其它的套接字地址信息;大家是不是發現,這些成員中的部分成員是不是有點似曾相識的感覺?比如,成員ai_family和我們前面章回中介紹套接字系統調用時的family表示的意思是相同的。其實,除了ai_flags,ai_canonname和ai_next這三個成員外,其它的幾個成員所表示的意思和我們前面章回中介紹套接字系統調用時表示的意思完全相同。我們只需要了解這三個新成員表示的意思就可以。
接下來我們介紹函數:getaddrinfo的使用方法:
該函數通過它的前兩個參數輸入數據,然後對數據進行處理,當輸入數據被處理完成後,通過它的第四個參數輸出數據。 它的第三個參數是可以看作是一個模板,輸出數據時依據該模板的格式來輸出; 該函數的第一個參數是char類型的指針,用來存放輸入的主機名或者IP地址; 該函數的第二個參數是char類型的指針,用來存放輸入的服務器名或者端口號; 該函數的第三個參數是addrinfo類型的指針,它用來控制輸出數據的格式,稍後詳細介紹; 該函數的第四個參數是addrinfo類型的二級指針,它用來存放函數輸出的數據,稍後詳細介紹; 該函數運行成功時返回0,運行失敗時返回非0值,不同的值代表不同類型的錯誤;該函數使用起來相對麻煩一些,麻煩性主要體現的參數上,下面我們詳細介紹一下最後兩個參數的用法:
第三個參數只使用了該結構體類型中的前四個成員,其它成員可以設置為0或者空指針。下面是關於該參數 中各個成員的取值集合,及其值的意義:
ai_flags用來控制函數的功能,經常用AI_ADDRCONFIG來賦值,該值表示返回本機的IP地址;它還有 其它值,我就不一一列舉了,大家可以自己查一下getaddrinfo的手冊。(查詢命令:man getaddrinfo) ai_family用來控制返回地址信息中套接字的域,大家都知道套接字的域決定了套接字的地址結構,因此,它本質上是在控制返回數據中套接字的地址結構,也就是成員ai_addr的結構。它的值是 AF_INET(IPV4 類型),AF_INET6(IPV6類型)和AF_UNSPEC中的任意一個,其中AF_UNSPEC表示所有的套接字域。 ai_socktype用來返回數據中套接字的類型,它的值是SOCK_STREAM,SOCK_DGRAM和0中的任意一個。 如果它的值為0,表示返回所有類型的套接字。 ai_protocol用來控制返回數據中套接字的協議,經常使用0給它賦值,表示使用默認的協議;第四個參數中,除了結構體成員中的第一個成員沒有使用外,其它的成員中都有相應的值,這些值是函數 運行的結果,各個成員的值的意義,我們在介紹addrinfo結構類型時已經介紹過了,因此,這裡不再介紹。我們重點說一下最後一個成員:
如果函數返回的數據中只有一個套接字地址,那麼它的值為空指針; 如果函數返回的數據中有兩個或者兩個以上套接字地址,那麼它會指向一個鏈表; 該鏈表中存放著重點內容所有的套接字地址; 該指針是鏈表的鏈接指針,鏈表通過該指針把鏈表中的成員連接在一起。 我們剛才所說的套接字地址鏈表是函數動態生成的,它會占用一定的內存空間,我們在使用完這些套接字 void freeaddrinfo(struct addrinfo *res);
使用該函數時,只需要把getaddrinfo函數中的最後一個參數傳給它就可以,它會自動去釋放參數中套接字地址鏈表占用的內存空間。
看官們,到目前為止在我們介紹的函數中,getaddrinfo函數算是比較難使用的函數了,不過,通過這個章回的介紹,我相信大家已經掌握了如何去使用該函數的方法,引用毛爺爺的詩詞來看,真是雄關漫道真如鐵,而今邁步從頭越呀。
各位看官,關於socket通信地址系統調用的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。