c语言实现dns数据结构算法,[转载]C++实现的DNS,包括域名过滤和缓存

1.程序体系结构

1.1 DNS体系结构

设计DNS的体系结构如图1-1所示。

a4c26d1e5885305701be709a3d33442f.png

图1-1 DNS体系结构逻辑图

其除了基本的域名解析功能,中包括对设定的域名的过滤以及DNS缓存等功能。具体功能流程将在后边程序具体实现中详细介绍。

1.2 Socket通信

a4c26d1e5885305701be709a3d33442f.png

图1-2 Socket通信逻辑功能图

设计的DNS实际即是一个服务器端又是一个客户端,这里主要起到一个桥梁作用,逻辑功能图如1-2所示。

2.数据结构设计

2.1 DNS报文数据结构

DNS报文数据结构参考RFC文档,设计的数据结构在头文件Structure.h中定义,下面详述介绍一下。

2.1.1 DNS Header

在RFC1034和RFC1035中对DNS进行了详细介绍,DNS报文格式如下:

a4c26d1e5885305701be709a3d33442f.png

其中对于Header结构具体如下:

a4c26d1e5885305701be709a3d33442f.png

对于C++/C语言来说自然想到的是位字段或者位域,表示一个字节中的各位数据。所以设计Header结构如图1-1所示:

a4c26d1e5885305701be709a3d33442f.png

图2-1 the structure of the DNS Header

2.1.2 Question Part

Question部分的数据结构如下所示:

a4c26d1e5885305701be709a3d33442f.png

当然这里要注意的是QNAME部分是可变的,所以设计数据需要特殊考虑,数据结构如图1-2所示。

a4c26d1e5885305701be709a3d33442f.png

图2-2 the structure of Question Part

2.1.3 Resource Record

在DNS报文协议中剩下的Answer,Authority以及Additional三部分格式都类似Resource

Record(RR)格式,形式如下所示:

a4c26d1e5885305701be709a3d33442f.png

其中,NAME和RDATA部分是可变的,其余部分固定。因此,设计数据结构如图1-3所示:

a4c26d1e5885305701be709a3d33442f.png

图2-3 the structure of RR

2.2 类的设计

通过前面介绍的程序体系结构的逻辑功能,如图1-1所示。这里自然可以想到类的设计就很明显了,类的分工明确。类的具体如下:

class DNS

类的定义与实现分别在文件DNS.h和DNS.cpp中,类的主要功能就是实现与客户端的通信。

class Filtrate

类的定义与实现分别在文件Filerate.h和Filtrate.cpp中,类的主要功能是实现对设定域名的过滤。

class Database

类的定义与实现分别在文件Database.h和Database.cpp中,类的主要功能是实现对相应DNS包的备份与缓存。

class QueryAndAnswer

类的定义与实现分别在QueryAndAnswer.h和QueryAndAnswer.cpp中,类的主要功能是实现与Foreign

Name

Server的通信,以及组织整个DNS工作流程,其中该类继承自类DNS,组合类Filtrate和类Database,可以说是整个程序的核心。

类的分工可以形象的如图2-4。

a4c26d1e5885305701be709a3d33442f.png

图2-4 类的分工逻辑图

3.程序具体设计与实现

3.1 程序执行流程

程序执行大致流程如图3-1所示。

a4c26d1e5885305701be709a3d33442f.png

图3-1 程序执行流程

程序首先初始化必要数据,完成初始化后偏自我阻塞,在53端口等待用户的查询的数据,当捕获用户的查询数据,首先解析其中Question中的域名,将此域名转换成正常顺序,然后到维护的过滤域名名单中查询,如果是要过滤的域名,此时不做任何处理,如果不是正常域名,则到自己缓存中去查询是否存在对此域名的缓存包,如果存在,则要进行适当的更改,比如标识字段,然后将封装完成的相应包发送给用户;如果不存在,则将此查询包转发给某个外部DSN,收到响应包后,先做必要缓存,然后再将此包转发给用户,至此,一次查询完成,程序继续等待用户请求。

3.2 程序设计

3.2.1 类DNS

类DNS主要实现与Client通信任务,捕获相应的数据包,进行必要解析已经将响应数据发送给Client,类的定义如图3-2所示。

a4c26d1e5885305701be709a3d33442f.png

图3-2 类DNS的定义

在类中,存储用户的查询数据包,分析其中要查询域名。同时,DNS也是一个基类,相应的数据成员设计成protected。

3.2.2 类Filtrate

类Filtrate的主要功能是实现过滤名单的查询,将维护过滤域名的文件中内容读入内存中,提供查询判断某一个域名是否在过滤名单中,这个功能在成员函数check()中实现。类的定义如图3-3所示。

a4c26d1e5885305701be709a3d33442f.png

图3-3 类Filtrate的定义

过滤文件名为filtrate.txt,其中添加了两个域名,分别为www.baidu.com和www.cntv.cn要过滤其他域名只需要向文件中添加必要信息即可,当然要重启程序。

3.2.3 类Database

类Database的主要功能是实现对相应DNS包的备份与缓存。类的具体定义如图3-4所示。

a4c26d1e5885305701be709a3d33442f.png

图3-4 类Database的定义

这部分功能本来打算不来实现的,后来发现这个实现过程真是异常的艰难,代码量超过了工程中其他工作量的总和。这里主要是实现对数据包的缓冲备份以及封装一个DNS响应包的功能,同时类中提供了相当数量的接口,具体代码请参考代码文件。

3.2.4 类QueryAndAnswer

a4c26d1e5885305701be709a3d33442f.png

图3-5 类QueryAndAnswer的定义

类QueryAndAnswer的主要功能是实现与Foreign Name

Server的通信,以及组织整个DNS工作流程,类的具体定义如图3-5所示。

类QueryAndAnswer继承自类DNS,组合了类Filtrate和Database的对象,是整个程序的核心。所有逻辑实现过程均在该类中实现。成员函数filtrate()通过Filtrate对象实现了对过滤域名的判断,成员函数RetriveDnsServersFormRegistry()用来获得在本地注册的DNS服务器地址,最关键的是成员函数operate(),整个程序的流程都是在这个成员函数中得到组织的。

3.3 注意内容

(1)DNS包中的域名跟正常的域名有很大不同,以www.google.com为例在包中的格式为3www6google3com’ ’。所以,在类Database中提供了两种方式的转换,这个两个成员函数分别是

(2)DNS响应包中的Answer域中第一个数据可能采用的是压缩方式,对于第一字节的最高两位如果都为’1’,则表明前两个字节是指针模式,指向Question域中的域名的位置,这样可以节省一部分空间。

(3)使用WinSock编程之前,在Window环境下要使用WSAStartup()装载必要库文件,同时这可能还会出问题,还要#pragma

comment(lib,

"WS2_32")来进一步完成上述工作,程序中的套接字编程使用的是最基本的数据报UDP套接字的阻塞方式。

4.结果分析与评价

4.1 实验结果

由于考虑到没有局域网的测试条件(当然后来也试过没问题),工程文件中提供了测试程序,下面是通过测试程序与本次实现的DNS程序之间的展示。

(1)程序启动会进行必要的初始化,执行结果如图4-1所示。

a4c26d1e5885305701be709a3d33442f.png

图4-1 DNS程序启动的必要初始化过程

(2)启动测试程序,然后输入要查询的域名,这里以www.google.com为例,在测试程序中会封装一个完成DNS

Query包发送给DNS服务器,这里也就是自己完成的这个DNS服务器,程序过程如图4-2所示。

a4c26d1e5885305701be709a3d33442f.png

图4-2 启动测试程序,输入查询内容

(3)DNS程序的操作显示,如图4-3所示。

a4c26d1e5885305701be709a3d33442f.png

图4-3 DNS程序操作显示

(4)测试程序收到DNS程序发送回来的DNS响应包,做必要解析后的结果如图4-4所示。

a4c26d1e5885305701be709a3d33442f.png

图4-4 测试程序收到返回结果

(5)测试程序发送一个要被DNS过滤的域名,前面已经讲过要过滤的域名,这里以www.baidu.com为例,操作结果如图4-5所示。

a4c26d1e5885305701be709a3d33442f.png

(6)DNS程序发现这是一个要过滤的域名,不做任何操作,如图4-6所示。

a4c26d1e5885305701be709a3d33442f.png

图4-6 DNS程序提示这是一个过滤的域名

4.2 分析与评价

(1)程序实现基本的DNS,使用的是简单的Socket阻塞通信模式,没有考虑并发以提高程序的运行效率。

(2)在Database中对DNS做缓存与备份出现了很多问题,有的现在还没有解决。单独封装一个DNS包,但是某些情况下不成功,这里可能对DNS协议需要进一步发掘。

这里要特别说明:

对于缓存与封装我试过两种方法,一种是完全自己封装一个DNS包,但是最后Additional

part貌似有问题导致包不能解析,我实在找不到错误在那里,前面部分没有问题。另一种方法就是对返回的DNS包做备份,但是这里同样有一个问题就是DNS包中有大量的' ',导致部分C语言函数难以完成,另外可以考虑string类的push_back()但是同样有一个问题,就是不知道包的大小,导致如果设定的包的大小过大,导致后面一堆“烫烫烫烫....”。当然这里两部分我都那代码实现了,如果谁要解决这个问题,我提供我写的源代码,期望你的参入。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值