DNS 服务器程序
实验报告
班级:2011211301
小组成员:曹晓欢 2011211139 杨静怡 2011211140
系统功能设计
设计一个DNS服务器程序,读入“IP地址-域名”对照表,当客户端查询域名对应的IP地址时,用域名检索该对照表,有三种可能检索结果:
检索结果:ip地址0.0.0.0,则向客户端返回“域名不存在”的报错消息(不良网站拦截功能)
检索结果:普通IP地址,则向客户端返回该地址(服务器功能) 表中未检到该域名,则向因特网DNS服务器发出查询,并将结果返给客户端(中继功能)
➢ 考虑多个计算机上的客户端会同时查询,需要进行消息ID
的转换
系统和运行环境描述
Windows7 操作系统平台,VS2010 编程环境。 使用 C/C++编写 dns 中继服务器。
主要数据结构
SOCKET sockfd; Socket套接字
SOCKADDR_IN ser_addr,nser_addr;
表达地址结构信息,等价于 sockaddr 结构
typedef struct req_inform {//DNS 请求包信息 SOCKADDR_IN cli_addr; unsigned short id; //id 和 cli_addr 唯一标识一个 DNS 请求 }req_inform;
该结构唯一标示了一个来自客户端的 dns 请求。
map url_ip_table; //本地域名解析表用来构建本地存储的 dnsrelay.txt 中域名和 IP 的映射。
map req_cache[cache_num];//id转换表 这一个 map 映射,把客户端 dns 请求映射到一个 unsigned short 上面,用它来存储 id 转换信息。Unsigned short类型的key值为新的id号,用于标识转发给外部服务器,而客户端的信息和旧id作为value存在map中,与key形成映射。待服务器发回应答包,根据包中id号,即可找到原id与客户端信息。#define cache_num 2//转换表数目
#define cache_size 500//每个转换表容量
int idThen_max=cache_num*cache_size; //总条目数 int cur_cache=0; int idThen=0;
cache_num 指定了 id 转换表的个数,cache_size 是每个 id 转换表的大小,
cur_cache 指向是当前正在装入的 id 转换表, idThen 是一个从 0 到 1000 一直循环的被映射到的 id 号。这样的设计可循环利用id转换表,并及时清除旧记录。
具体流程是:
生成 id 转换的 item(idThen,struct req_inform 的一个变量) 把 id 转换的 item 加入到 req_cache[cur_cache]中 如果 req_cache[cur_cache]已经达到 cache_size {
cur_cache 指向下一个 id 转换表,并将其清空 }
idThen 加 1
函数划分(模块划分)
int get_url_ip_table(map &iptable) //失败返回-1 从文件中读入 url和ip的映射表。int init();
用来初始化 ser_addr、nser_addr、sockfd,以及对 sockfd 绑定到本地的 ser_addr 的 地址上。
int is_req(char * buffer);
用来判断收到的包是上级服务器的回答包,还是来自客户端的请求包。
void get_url(char * buf,string & url); 从请求包中提取 URL。
void ask_next_server(char * buffer,struct sockaddr_in req_addr,int buffer_size); 询问上级 dns 服务器。
void create_respose(char *buffer,struct sockaddr_in req_addr,int buffer_size,string ip);
根据 url-ip 表中找到的结果自己构造响应。
void deal_req(char * buffer,struct sockaddr_in req_addr,int buffer_size); 客户端请求包的处理
void deal_res(char * buffer,int buffer_size);
上级服务器回答包的处理。
int main(); 主函数
软件流程图
开始 失败 读入url-ip表 成功 结束 失败 初始化 结束 成功 接收数据包 获取DNS报头 请求包 包类型 应答包 DNS 检索映射表,修改ID 本地解析 发送至客户端 本地找到 NO YES 向上级服务器询问 构造相应包
否
是否结束
是 结束
源代码
#include #include #include