程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> DIY一個DNS查詢器:程序實現

DIY一個DNS查詢器:程序實現

編輯:C#入門知識

 

上一篇文章《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}\n",mydns.header.ANCOUNT) );

         txtInfo.AppendText(string.Format("回復額外記錄數:{0}\n", 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()+"\n");

         }

界面截圖:

MydnsSearch

 

代碼下載及浏覽:

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

歡迎園友測試。如果發現錯誤,請告知我

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved