zoukankan      html  css  js  c++  java
  • DIY一个DNS查询器:程序实现

    上一篇文章《DIY一个DNS查询器:了解DNS协议》中讲了DNS查询协议的原理和数据结构。经过两个星期的开发,完成了该查询器的编写。期间也遇到了一些问题,如:

    1资源记录(Resource Record)中的RDData内容的格式。

    2关于压缩编码的指针问题。

    3代码冗余结构不清晰。

    尤其是压缩编码的问题,困扰了我很久,找了很多中文资料,都说到当长度的值为“192”的时候为指针,下一字节的内容即偏移的位置,但是在过程中却发现存在该值为“193”的情况,一直不解了好久。这里我给解释下:

    假设第13字节内容为:05-6c-69-78-69-6e-02-6d-6e

    翻译为“5-l-i-x-i-n-2-m-e”

    而其后的某个地方,同样出现了lixin.me的字符串,那么就会使用指针编码:"c0-0c”。

    c0十进制是192,代表下面的内容是一个指针,0c是个地址,指向了data[12]的位置。

    而为什么会出现193呢,也好理解,因为用一个字节的内容来表示偏移,顶多也只能偏移256个字节,那么假设udp包有500个字节长,而要指向第300字节就无能为力了。因此实际上的偏移量不是由oc这个字节内容决定的,正确的偏移量是:(Cn-C0)*256+0c。

    如果值为193,下一字节为1,那么具体偏移就是 (193-192)*256+1 。

    还有一点要注意到就是可变长度的Name字段以什么为结尾。有3中结尾方式:

    1.长度+内容+~+长度0

    2. 偏移标识+偏移量

    3.长度+内容+~+偏移标识+偏移量

    能成功解决该问题,主要还是靠资料,虽然知道rfc1034和rfc1035里面一定有我要的内容,可惜外文比较难懂,一直看不下去,通过搜索得到的中文和少量外文资料也没说清楚。最后还得感谢《TCP-IP详解卷一:协议》的第14章Dns协议的介绍,虽然只有短短的17页,但还是帮我解决了问题。所以在同样搞协议的同学,不妨弄本先去瞧瞧,或者遇到问题也可以先去看看。

    现在来说说这个程序了。

    我按dns协议的结构把项目分成 MyDnsHeader.cs、MyDnsQuestion.cs、MyDnsRecord.cs 这样的3个大结构。

    发送dns请求时只需要构造MyDnsHeader和MyDnsQuestion结构,然后通过GetBytes()函数得到构造好的字节数组,然后通过udp发送出去。然后接受来自服务器的响应,将接收到的字节数组通过Parse(byte[] recvData)方法让3个结构去解析,最后通过这些结构的属性字段获取相应的查询信息。

    其中的资源记录,目前能分析 A记录、SOA记录、TXT记录、CNAME记录、MX记录、NS记录。

    示例代码:

             MyDns mydns = new MyDns();//

             //想8.8.8.8域名服务器查询lixin.me这个域名的a记录, 
             if (!mydns.Search(“lixin.me”QueryType.A, “8.8.8.8”,null )) 
             {

                 //如果服务器返回错误信息,则显示错误的内容

                 MessageBox.Show(mydns.header.RCODE.ToString()); 
                 return; 
             } 
             txtInfo.Clear(); 
             txtInfo.AppendText (string.Format ("回复记录数:{0} ",mydns.header.ANCOUNT) ); 
             txtInfo.AppendText(string.Format("回复额外记录数:{0} ", mydns.header.ARCOUNT )); 
             txtInfo.AppendText(string.Format("回复权威记录数:{0}", mydns.header.NSCOUNT ));

             txtContent.Clear(); 
             foreach (MyDnsRecord item in mydns.record.Records) 
             {

                //循环资源记录,并打印出来。 
                 txtContent.AppendText(item.QType.ToString() + "   " + item.RDDate.ToString()+" "); 
             }

    界面截图:

    MydnsSearch

    代码下载及浏览:

    我把代码放在了CodePlex.com 上面了。地址为:http://mydnspackage.codeplex.com/

    欢迎园友测试。如果发现错误,请告知我。

  • 相关阅读:
    Nginx配置文件nginx.conf中文详解(转)
    windows Nginx基本使用方法
    phpstorm 找到文件修改历史
    微信小程序模拟点击出现问题解决方法
    设置头像、商品、轮播图为背景图时需要的css
    div左右居中css
    自定义方形复选框
    css 调转180度:transform: rotate(180deg);
    js字符串转数字(小数),数字转字符串
    腾讯地图key秘钥
  • 原文地址:https://www.cnblogs.com/xumaojun/p/8541571.html
Copyright © 2011-2022 走看看