我們現在認知一台計算機主機通常采用直觀可讀的名字。例如博客園我們會記住 www.cnblogs.com 而不是記住42.121.252.58這個IP。對於大多數的應用程序來說應該是處理名字而不是處理地址。如果說對於一個點分十進制來說還好記住,那么當使用IPv6時,IP地址就不是那么好記了。
下面將介紹Linux下的一個函數 gethostbyname ,查找主機名最基本的函數。如果調用成功,它就返回一個指向hostent結構的指針,該結構中含有所查找主機的所有IPv4地址。這個函數的局限是只能返回IPv4地址,getaddrinfo函數是同時能處理IPv4和IPv6地址,不過這個不在討論的范圍。
函數的定義:
1 #include <netdb.h>
2 struct hostent * gethostbyname(const char * hostname); //返回:若成功則為非空指針,若出錯則為NULL且設置h_errno
hostent 結構如下:
1 struct hostent{ 2 char *h_name; /*official (canonical ) name of host*/
3 char **h_aliases; /*pointer to array of pointers to alias names*/
4 int h_addrtype; /*host address type:AF_INET*/
5 int h_length; /*length of address: 4*/
6 char **h_addr_list; /*ptr to array of ptrs with IPv4 addrs*/
7 };
h_name是正式的主機名,h_aliases是主機的別名。h_addrtype一般是AF_INET表示使用IP。h_length表示地址長度,而IPv4是4個字節。最后的h_addr_list表示地址對應的所有IP地址。(Ps:一個地址有多個IP對應,一般是用於負載吧,比如一個大型網站可能南方,北方,國外等不同的地方都有主機,不同的IPS也會有不同的IP,總之是很多情況。需要多個IP)。
一個調用gethostbyname並顯示返回的信息的簡單例子。
1 #include <stdio.h>
2 #include <arpa/inet.h>
3 #include <netdb.h>
4
5
6 int main(int argc,char **argv) 7 { 8 char *ptr,**pptr; 9 char str[INET_ADDRSTRLEN]; 10 struct hostent *hptr; 11
12 while(--argc>0)//判斷參數的個數是否合法
13 { 14 ptr=*++argv;//取第一個參數及以后
15 if((hptr=gethostbyname(ptr))==NULL)//開始獲取
16 { 17 printf("gethostbyname error for host: %s: %s\n",ptr,hstrerror(h_errno));//出錯信息,並記錄在h_error中
18 continue; 19 } 20 printf("official hostname: %s\n",hptr->h_name);//正式主機名
21
22 for(pptr=hptr->h_aliases;*pptr!=NULL;pptr++)//遍歷所有的主機別名
23 printf("\talias: %s\n",*pptr); 24
25 switch(hptr->h_addrtype)//判斷socket類型
26 { 27 case AF_INET: //IP類為AF_INET
28 pptr=hptr->h_addr_list; //IP地址數組
29 for(;*pptr!=NULL;pptr++) 30 printf("\taddress: %s\n", 31 inet_ntop(hptr->h_addrtype,*pptr,str,sizeof(str)));//inet_ntop轉換為點分十進制
32 break; 33 default: 34 printf("unknown address type\n"); 35 break; 36 } 37 } 38 return 0; 39 }
編譯 gcc hostent.c -o hostent
那個Server: 202.96.134.133是本地的dns ,在/etc/resolv.conf 中。
程序在CentOS6.4中運行成功。參考UNP這本書。