Linux網路程式設計[DNS解析原理,瞭解相關DNS解析的函式]
阿新 • • 發佈:2019-02-16
Linux網路程式設計[淺析DNS原理,瞭解相關DNS解析的函式]
1.DNS解析的相關原理
2. 域名解析的相關函式
###埠繫結, DNS解析的相關原理
先通過一張圖示來展示一下什麼是DNS:
1:每一個域名都是與ip進行繫結的
2:瀏覽器在訪問域名的時候,會自動解析出對應繫結的ip地址
3:整個解析過程涉及到域名解析與域名伺服器
在自己的本機怎麼去進行域名和ip的繫結呢??
linux系統下,可以在本地本間中去設定:
開啟/etc/hosts檔案:
從我本機的hosts檔案中可以看到,對應的ip繫結的主機名和自己設定的域名.第一個域名dean稱為正式的主機名字,第二個以後都稱為別名
域名解析的相關函式
1**:域名解析函式中的結構體**
struct hostent{
char *h_name ;//正式主機名字(第一個域名)
char **h_aliases;//主機的別名(主機的別名對應的)
int h_addrtype;//協議型別
int h_length;//網路地址大小
char **h_addr_list;//指向網路地址的指標
};
上述的結構體放置的就是域名解析出來後放置的結構體
從上述圖示中可以看出來,h_aliases指向的都是一個數組
h_addr_list指向的也是一個ip地址的陣列,所以使用的都是二級指標
2:域名解析相關函式
#include<netdb.h> struct hostent *gethostent(void); //會將整個hosts檔案下記錄的主機和域名相對應的所有組全部遍歷出來 strct hostent *gethostbyname(const char *hostname); 引數:hostname 域名,獲取的是指定的hostent 注意: gethostbyname是不支援ipv6的,並且在多執行緒的情況下是不穩定的.所有一般情況下都是使用gethostent來進行操作的 void sethostent(int stayopen); void endhostent(void);
虛擬碼案例部分
struct hostnet *hptr;
if((hptr = gethostbyname("www.google.com")) == NULL){
printf(stderr,"gethostbyname call failed.%s\n",hosterror(h_errno));
return -1;
}
//輸出h_name(正式域名)
printf("offical name:%s\n",hptr->h_name);
//輸出別名:
for(pptr = hptr->h_aliases;*pptr!=NULL,pptr++){
printf("\t aliases:%s\n",*pptr);
}
//輸出網路型別
if(hptr->h_addrtype != AF_INET){
fprintf(stderr,"invalid address type %d\n",hptr->h_addrtype);
return -1;
}
pptr = hptr->h_addr_list;
for(;*pptr!=NULL;pptr++){
printf("\t address:%s\n",inet_ntop(hptr->h_addrtype,*pptr,str,sizeof(str)));
}
gethostbyname部分的例項程式碼
/*
* ===========================================================================
*
* Filename: gethostbyname.c
* Description:
* Version: 1.0
* Created: 2017年05月14日 21時52分34秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<stdio.h>
#include<stdlib.h>
#include<netdb.h>
#include<string.h>
#include<sys/socket.h>
void out_host(struct hostent *h){
//獲取主機名稱
char *host_name = h->h_name;
printf("host_name:%s\n",host_name);
//獲取網路型別
int host_addrtype = h->h_addrtype;
if(host_addrtype == AF_INET){
printf("addrtype:IPV4\n");
}else{
printf("addrtype:IPV6\n");
}
//獲取主機網路地址的大小
int host_length = h->h_length;
printf("host_length:%d\n",host_length);
//獲取主機的ip,主機的ip對應的是網路地址陣列中的0,記住要將網路位元組序轉換成主機位元組序號
char ip[16];
memset(ip,0,sizeof(ip));
inet_ntop(h->h_addrtype,h->h_addr_list[0],ip,sizeof(ip));
printf("host ip:%s\n",ip);
//遍歷去獲取別名
int aliase_count = 0;
while( h->h_aliases[aliase_count] != NULL){
printf("host_aliases[%d]:%s\n",aliase_count,h->h_aliases[aliase_count]);
aliase_count++;
}
//獲取指向網路地址的陣列,
int host_addr_list_count = 0;
while(h->h_addr_list[host_addr_list_count] != NULL){
memset(ip,0,sizeof(ip));
inet_ntop(h->h_addrtype,h->h_addr_list[host_addr_list_count],ip,sizeof(ip));
printf("host_addr_list[%d]:%s\n",host_addr_list_count,ip);
host_addr_list_count++;
}
}
int main(int argc,char *argv[]){
if(argc < 2){
printf("usag %s host \n",argv[0]);
exit(EXIT_FAILURE);
}
struct hostent *h;
//通過gethostbyname來獲取hostent的結構體指標
h = gethostbyname(argv[1]);
if(h == NULL){
printf("no host :%s\n",argv[1]);
}else{
out_host(h);
}
endhostent();
return 0;
}
gethostent部分的例項程式碼
/*
* ===========================================================================
*
* Filename: gethostent.c
* Description:
* Version: 1.0
* Created: 2017年05月14日 22時14分48秒
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<memory.h>
void out_host(struct hostent *h){
//獲取主機名稱
char *host_name = h->h_name;
printf("host_name:%s\n",host_name);
//獲取網路型別
int host_addrtype = h->h_addrtype;
if(host_addrtype == AF_INET){
printf("addrtype:IPV4\n");
}else{
printf("addrtype:IPV6\n");
}
//獲取主機網路地址的大小
int host_length = h->h_length;
printf("host_length:%d\n",host_length);
//獲取主機的ip,主機的ip對應的是網路地址陣列中的0,記住要將網路位元組序轉換成主機位元組序號
char ip[16];
memset(ip,0,sizeof(ip));
inet_ntop(h->h_addrtype,h->h_addr_list[0],ip,sizeof(ip));
printf("host ip:%s\n",ip);
//遍歷去獲取別名
int aliase_count = 0;
while( h->h_aliases[aliase_count] != NULL){
printf("host_aliases[%d]:%s\n",aliase_count,h->h_aliases[aliase_count]);
aliase_count++;
}
int host_addr_list_count = 0;
while(h->h_addr_list[host_addr_list_count] != NULL){
memset(ip,0,sizeof(ip));
inet_ntop(h->h_addrtype,h->h_addr_list[host_addr_list_count],ip,sizeof(ip));
printf("host_addr_list[%d]:%s\n",host_addr_list_count,ip);
host_addr_list_count++;
}
}
int main(int argc,char *argv[]){
if(argc < 2){
printf("usage: %s host\n",argv[0]);
exit(EXIT_FAILURE);
}
struct hostent *h;
//因為gethost返回的是一個結構體陣列
while((h = gethostent()) != NULL){
if(strcmp(argv[1],h->h_name) == 0){
out_host(h);
}else{
int aliases_count = 0;
while(h->h_aliases[aliases_count] != NULL){
if(strcmp(argv[1],h->h_aliases[aliases_count]) == 0){
out_host(h);
exit(EXIT_FAILURE);
}
aliases_count++;
}
}
}
endhostent();
return 0;
}
以上除了虛擬碼部分,gethostbyname.c個gethostent.c的程式碼都是直接可以進行run的,在使用的時候相對來說是比較推薦去使用gethostent的,因為gethostbyname不支援ipv6以及不建議在多執行緒情況下去使用的.當然,這也只是簡單的去了解下dns去在解析的時候的簡單的原理.