1. 程式人生 > >Linux網路程式設計--IP地址與域名解析(DNS)

Linux網路程式設計--IP地址與域名解析(DNS)

在日常生活中,人們往往知道主機的域名而不知道主機的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; }