基于Reactor的DNS客户端

背景

网络编程中常用getaddrinfo()函数,从DNS地址获取ip地址。但该函数会阻塞调用线程,是个租塞的调用。

使用Reactor网络库上采用非阻塞方式编写一个DNS客户端,获得ip地址。

设计与实现

一言蔽之,先实现DNS请求和DNS解析。再将DNS请求和DNS解析地逻辑放在libevent框架下即可实现非阻塞dns客户端。

DNS请求和DNS解析

前提知识:

对比报文格式写结构体

typedef struct //DNS message header
{
    unsigned short id;
    unsigned short flags;
    unsigned short questNum;
    unsigned short answerNum;
    unsigned short authorNum;
    unsigned short additionNum;
} DNSHDR, *pDNSHDR;

typedef struct //DNS message request recored
{
    unsigned short type;
    unsigned short queryclass;
} QUERYHDR, *pQUERYHDR;

typedef struct //DNS message response recored
{
    unsigned short type;
    unsigned short classes;
    unsigned int ttl;
    unsigned short length;
} RESPONSE, *pRESPONSE;

将域名放到请求报文中就不细讲了,仔细就能够做出来;在解析回复报文时,用char*指针指向回复内容,根据报文格式解析各个部分。其中有几个地方容易出错。

  1. 最好使用unsigned char*代替char*。使用char*打印数据时,有时会出现莫名其妙的数据,如0xc0会显示成0xfffffc0。
  2. 在解析完一个区域,挪动指针时。如解析完RESPONSE,pTraceResponse+=sizeof(RESPONSE),很容易出错。RESPONSE内部时3个short和一个int数据,加起来应该等于10,但是由于结构体对齐,sizeof(RESPONSE)返回12.因此在声明RESPONSE结构体时,可加上__attribute__ ((packed))
  3. 注意网络的大小端。在解析flag时,我没有使用htons函数,练了一下手,自己用wireshark抓包对比着写的解析函数。
    //将DNS应答报文的“标志”字段右移15位即取最高位 , 0 为DNS查询报文,1为应答报文
        //没有使用htons,由于网络字节序字节15变成7位
        if (pDnsHdr->flags >> 7)
        //
        {
            //flags低位值为3,标识服务器没有与请求域名相应的记录
            if (((pDnsHdr->flags >> 4) & 0x0007) != 0)
            {
                printf("No corresponding domain name entry . \n");
                return;
            }
            if ((pDnsHdr->flags >> 2) & 0x0001) //查看标志位AA,看是否时权威应答
            {
                printf("Authoritative anwser : \n");
            }
            else
            {
                printf("None-authoritative anwser : \n");
            }

    Reactor网络库--libevent

前提知识:

前面实现了DNS报文的请求,实现了后面就简单了。只需要编译libevent,将自己的DNS请求交给libevent管理。

  1. 编译libevent:https://aceld.gitbooks.io/libevent/content/chapter1.html
  2. code完事儿

最重要的show me the code:GitHub - ltCodeW/Reactor_DNSclient: 使用Reactor框架libevent写的DNS客户端

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值