您的位置:首页 > 理论基础 > 计算机网络

Linux网络编程[DNS解析原理,了解相关DNS解析的函数]

2017-05-14 22:39 1296 查看

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去在解析的时候的简单的原理.

欢迎持续访问博客

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息