Linux網路程式設計--IP地址與域名解析(DNS)
阿新 • • 發佈:2019-01-02
在日常生活中,人們往往知道主機的域名而不知道主機的IP地址,而socket的API均基於IP地址,所以需要使用DNS域名解析伺服器進行解析。
那麼首先簡單介紹一下DNS的原理,DNS伺服器系統是按樹形的結構構造,頂級域名伺服器下分多個二級域名伺服器,二級域名伺服器下面又分多個下級域名伺服器,每個伺服器都下轄了一些主機,如圖所示:
那麼一個主機是如何查詢一個域名的IP地址呢?首先需要想本地的域名伺服器查詢,如果沒有就向上級域名服務查詢,如果二級的也查不到就會向頂級域名伺服器查詢,如果頂級的也查不到,那麼就會返回錯誤。如圖是 本地主機查詢目標主機的DNS查詢過程:
Linux系統提供了獲取主機資訊的函式,gethostbyname(),gethostbyaddr(),兩者都會用到一個結構體,結構體資訊如下:
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
#define h_addr h_addr_list[0] /* for backward compatibility */
函式gethostbyname和gethostbyaddr也具有不可重入性,返回結果儲存在靜態變數中,後者結果會覆蓋前者,使用時要注意。
使用gethostbyname和gethostbyaddr的例子:
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
int main(int argc, char *argv[])
{
struct hostent *ht=NULL;
/* 查詢的主機域名 */
char host[]="www.sina.com.cn";
#if 1
struct hostent *ht1=NULL, *ht2=NULL;
char host1[]="www.sohu.com";
/* 查詢主機www.sina.com.cn */
ht1 = gethostbyname(host);
ht2 = gethostbyname(host1);//函式的不可重入性,前者結果已經被覆蓋
int j = 0;
#else
struct in_addr in;
in.s_addr = inet_addr("60.215.128.140");
ht = gethostbyaddr(&in, sizeof(in), AF_INET);
#endif
for(j = 0;j<2;j++){
if(j == 0)
ht = ht1;
else
ht =ht2;
printf("----------------------\n");
if(ht){
int i = 0;
printf("get the host:%s addr\n",host); /* 原始域名 */
printf("name:%s\n",ht->h_name); /* 名稱 */
/*協議族AF_INET為IPv4或者AF_INET6為IPv6*/
printf("type:%s\n",ht->h_addrtype==AF_INET?"AF_INET":"AF_INET6");
/* IP地址的長度 */
printf("legnth:%d\n",ht->h_length);
/* 列印IP地址 */
for(i=0;;i++){
if(ht->h_addr_list[i] != NULL){/* 不是IP地址陣列的結尾 */
printf("IP:%s\n",inet_ntoa((unsigned int*)ht->h_addr_list[i])); /*列印IP地址*/
} else{/*達到結尾*/
break; /*退出for迴圈*/
}
}
/* 列印域名地址 */
for(i=0;;i++){/*迴圈*/
if(ht->h_aliases[i] != NULL){/* 沒有到達域名陣列的結尾 */
printf("alias %d:%s\n",i,ht->h_aliases[i]); /* 列印域名 */
} else{/*結尾*/
break; /*退出迴圈*/
}
}
}
}
return 0;
}