gethostbyname 和 gethostbyname_r(可重入的)得到dns資訊
#include <netdb.h>
#include <sys/socket.h>
struct hostent *gethostbyname(const char *name);
這個函式的傳入值是域名或者主機名,例如"www.google.com","wpc"等等。
傳出值,是一個hostent的結構(如下)。如果函式呼叫失敗,將返回NULL。
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
解釋一下這個結構, 其中:
char *h_name 表示的是主機的規範名。例如www.google.com的規範名其實是www.l.google.com。
char **h_aliases 表示的是主機的別名。www.google.com就是google他自己的別名。有的時候,有的主機可能有好幾個別名,這些,其實都是為了易於使用者記憶而為自己的網站多取的名字。
int h_addrtype 表示的是主機ip地址的型別,到底是ipv4(AF_INET),還是ipv6(AF_INET6)
int h_length 表示的是主機ip地址的長度
int **h_addr_lisst 表示的是主機的ip地址,注意,這個是以網路位元組序儲存的。千萬不要直接用printf帶%s引數來打這個東西,會有問題的哇。所以到真正需要打印出這個IP的話,需要呼叫inet_ntop()。
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :
這個函式,是將型別為af的網路地址結構src,轉換成主機序的字串形式,存放在長度為cnt的字串中。
這個函式,其實就是返回指向dst的一個指標。如果函式呼叫錯誤,返回值是NULL。
下面是例程,有詳細的註釋。
#include <netdb.h>
#include <sys/socket.h>
int main(int argc, char **argv)
{
char *ptr,**pptr;
struct hostent *hptr;
char str[32];
/* 取得命令後第一個引數,即要解析的域名或主機名 */
ptr = argv[1];
/* 呼叫gethostbyname()。呼叫結果都存在hptr中 */
if( (hptr = gethostbyname(ptr) ) == NULL )
{
printf("gethostbyname error for host:%s/n", ptr);
return 0; /* 如果呼叫gethostbyname發生錯誤,返回1 */
}
/* 將主機的規範名打出來 */
printf("official hostname:%s/n",hptr->h_name);
/* 主機可能有多個別名,將所有別名分別打出來 */
for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
printf(" alias:%s/n",*pptr);
/* 根據地址型別,將地址打出來 */
switch(hptr->h_addrtype)
{
case AF_INET:
case AF_INET6:
pptr=hptr->h_addr_list;
/* 將剛才得到的所有地址都打出來。其中呼叫了inet_ntop()函式 */
for(;*pptr!=NULL;pptr++)
printf(" address:%s/n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
break;
default:
printf("unknown address type/n");
break;
}
return 0;
}
*******************************************************************************************************************************
使用gethostbyname_r得到dns資訊
在使用前需要看看所使用系統是否有這個函式
但是因為gethostbyname返回的是一個指向靜態變數的指標 不可重入
很可能剛要讀時值就被其它執行緒修改
所以 新的posix中增加了另一個可重入的從主機名(域名)得到DNS的孫數
gethostbyname_r
下面是它用法的簡單例子
CODE
#include <netdb.h>
#include <stdio.h>
#include <netinet/in.h>
#define DUMP(...) printf(__VA_ARGS__)
int main(int argc,char** argv)
- {
| char buf[1024];
| struct hostent hostinfo,*phost;
| int ret;
|
| DUMP("argc:%d\n",argc);
- if(argc <2 ){
2 printf("ERROR:test domainname\n");
2 return 1;
2 }
|
| if(gethostbyname_r(argv[1],&hostinfo,buf,sizeof(buf),&phost,&ret))
| printf("ERROR:gethostbyname(%s) ret:%d,phost:%d\n",argv[1],ret,(int)ph
| ost);
- else{
2 int i;
printf("gethostbyname(%s) success:ret:%d,",argv[1],ret);
2 if(phost)
2 printf("phost(%d):name:%s,addrtype:%d(AF_INET:%d),len:%d,addr[0]:%
2 d,[1]:%d\n",
2 (int)phost,phost->h_name,phost->h_addrtype,AF_INET,
2 phost->h_length,
2 (int)phost->h_addr_list[0],
2 phost->h_addr_list[0] == NULL?0
2 :(int)phost->h_addr_list[1]);
2 for(i = 0;hostinfo.h_aliases[i];i++)
2 printf("host(%d) alias is:%s\n",(int)&hostinfo,hostinfo.h_aliases[
2 i]);
2 for(i = 0;hostinfo.h_addr_list[i];i++)
2 printf("host addr is:%s\n",inet_ntoa(*(struct in_addr*)hostinfo.h_
2 addr_list[i]));
2 }
|
| return 0;
| }