Click here to Skip to main content
15,883,731 members
Articles / Programming Languages / C#
Article

Test Your DNS Response Times with DNS Tester

Rate me:
Please Sign up or sign in to vote.
4.45/5 (24 votes)
27 Mar 20076 min read 257.9K   7.1K   69   36
Check the response times of your DNS and compare with other servers.

DNS Tester Screenshot

Introduction

This article discusses a tool that can be used to analyse your DNS performance. It checks the timing of DNS requests between two DNS servers, and displays the results. Download the tool and enter your DNS. I suggest testing it against 4.2.2.1 which I have found to be a very good public DNS. Enter your proxy if needed, and click Test. A few seconds later, you can compare your DNS with 4.2.2.1.

Background

Recently, I had problems with web pages not displaying the first time they were used. If I refreshed the web page, it would then display. I suspected problems with DNS, and seemed to resolve the problem by interchanging the primary and secondary DNS that my provider assigned. Although this seemed to work, I didn't really know why, and then decided to create an analysis tool to check the DNS performance. (For a review of DNS fundamentals - see the CodeProject article by Pawan Bangar titled "Know How DNS Works".)

When a web page is displayed, the first request is a DNS query to resolve the domain name, such as www.google.com, into an IP address. If this name resolution is slow, then web pages may be slow to load, or timeout. Normally, you have two DNS servers assigned so that if the primary DNS server fails to respond, then the secondary is used.. The sequence of queries is:

  • Ask the primary DNS to resolve the name.
  • If times out after 1 second with no response, ask the secondary DNS.
  • If times out after 2 seconds, ask the primary DNS and ask the secondary DNS.
  • If times out after 4 seconds, ask the primary DNS and ask the secondary DNS.

Normally, there will be a response with a name resolution for the first question, so the escalation sequence is not required. The DNS server will respond with the name resolution if known, or else, it will pass the request to another DNS server (higher in the chain - so to speak) for resolution. When the DNS server is required to ask for another DNS server to resolve the name, then it caches this name and IP resolution so that if the same name resolution is required later, then it is known. (This name resolution is also cached by your own router.)

There are quite a few DNS response tools on the internet such as www.dnsstuff.com, but all the DNS requests that are made by these tools are from their location, and so timings may be different. In addition, many providers have closed their DNS servers so that they can only be used by their customers.

Using the code

When a DNS request is made, the returned answer is cached by the DNS server so that the second time a DNS request is made, then another request will return the result immediately because of local caching. In order to find out the real DNS performance, I use Google to compile a list of random web sites.

First, make a random three character alphabetic string. (I can imagine that some people will cringe at this blatant misuse of a function, but it was quick!)

C#
RNGCryptoServiceProvider rng = 
        new RNGCryptoServiceProvider();
rng.GetBytes(random); 
// The array is now filled with random bytes.
for (i=1;i<256;i++)
{
   // Just take the first three letters
   if (random[i] > 0x40 && random[i] < 0x5b)
       Letters=Letters+Convert.ToChar(random[i]);
   if (Letters.Length == 3) break;
}

Then, use this random string to make a Google search:

C#
WebRequest GoogleRequest = 
  WebRequest.Create("http://www.google.com" + 
                    "/search?num=100&q="+Letters);
WebResponse GoogleResponse = GoogleRequest.GetResponse();
Application.DoEvents();
// Get the response stream.
Stream GoogleStream = GoogleResponse.GetResponseStream();
StatusBoxPrint("Google response received");
// Use a StreamReader to read the entire response
StreamReader GoogleReader = new 
   StreamReader(GoogleStream, Encoding.ASCII);
string GoogleString = GoogleReader.ReadToEnd();
// Close the response stream
// and response to free resources.
GoogleStream.Close();
GoogleResponse.Close();

Now, parse this received web page for web addresses ending in ".???.com":

C#
Regex Dotcom = new Regex("[.]([A-Za-z]*)[.]com"); 
// Use the Matches method to find
// all matches in the input string.
HostNames = Dotcom.Matches(GoogleString);

Then, duplicate names are removed and the domain names are used for the DNS requests. A socket is created for UDP, and DNS requests are made to the two DNS servers at the same time. The current time is saved before the DNS requests are sent so that the delta time can be calculated. A DNS packet contains two bytes at the beginning to enable the requester to keep track of the answers, called transactionID. These bytes are set to "Q1" or "Q2" for the request. This is a little unorthodox, but when an answer is received, this allows easy checking of whether the received packet is relevant to this program and determines the DNS server that has responded.

C#
Socket DNSsocket = new Socket(AddressFamily.InterNetwork, 
       SocketType.Dgram, ProtocolType.Udp);
DNSsocket.SetSocketOption(SocketOptionLevel.Socket, 
       SocketOptionName.ReceiveTimeout, DNSReceiveTimeout);
IPEndPoint dnsEP1 = new 
   IPEndPoint(IPAddress.Parse(DNSAddress1),IPPort);
IPEndPoint dnsEP2 = new 
   IPEndPoint(IPAddress.Parse(DNSAddress2),IPPort);

// Start the clock
StartTime=DateTime.Now.Ticks;

for (i=0;i<URLNamescount;i++)
{
   URLNameStart = 
     URLNames[i].Substring(0,URLNames[i].IndexOf("."));
   DomainName = 
     URLNames[i].Substring(URLNames[i].IndexOf(".")+1, 
     URLNames[i].Length - URLNames[i].IndexOf(".")-1);
   // Build the query 
   QueryString = TransactionID1 + TypeString + 
                (char)URLNameStart.Length + 
                 URLNameStart + (char)DomainName.Length + 
                 DomainName + TrailerString;
   Sendbytes = Encoding.ASCII.GetBytes(QueryString);
   DNSsocket.SendTo(Sendbytes, Sendbytes.Length, 
                    SocketFlags.None, dnsEP1);

   // send the same message to both DNS servers
   // except for the transaction ID
   QueryString = TransactionID2 + TypeString + 
                (char)URLNameStart.Length + 
                 URLNameStart + (char)DomainName.Length + 
                 DomainName + TrailerString;
   Sendbytes = Encoding.ASCII.GetBytes(QueryString);
   DNSsocket.SendTo(Sendbytes, Sendbytes.Length, 
                    SocketFlags.None, dnsEP2);
}

When answers are received, they are checked as valid "Q1" or "Q2" and decoded. The request made is added to the listview and displayed. If no more answers arrive after timeout, then we can analyse the data and test again.

Points of interest

An excellent CodeProject article "C#.NET Query Component" by Rob Philpot formed the starting point for the DNS requests. At first look, these methods looked too difficult for me, so I tried a few other ways of checking DNS. I started by trying the Dns.Resolve method, and also tried Dns.GetHostByName. This method was able to get DNS answers, but I ran into a brick wall when I needed to get the DNS from a different server. The Dns.Resolve method uses the computer defined DNS. I experimented with using netsh to change the DNS, but I found that this seemed to take several seconds. Then, I got a hint on the net from Eric Meyers on www.dotnet247.com to use nslookup and call it using Start.Process. This seemed to be a way around the inability of Dns.Resolve to use multiple DNS servers, but I found that I could not call this with window minimized for some reason. At this time, I also saw that using these ideas to check the DNS of 30 or 40 names would be very time consuming at several seconds per check. I moved over to the UdpClient class. The UdpClient.Send method worked okay for sending multiple DNS requests, but the UdpClient.Receive would not work for me. There seemed to be no way to stop listening! I saw several references on websites that this class should be avoided like the plague, and I can agree with this.

I finally came back to the socket class, and got it working for me. One tool that I found extremely helpful was Ethereal. It is an open source Ethernet protocol analyser which is available for download here. For examining just the UDP DNS packets, set the filter to "port 53".

One thing that really opened my eyes was how my ISP provider DNS drops requests. I have found that the best public DNS is 4.2.2.1. Comparing this public DNS against my DNS shows that my DNS drops about half the requests! UDP packets used by DNS can be lost and, unlike TCP, is not a guaranteed delivery protocol. In this program, I only ask the DNS for the A record once. If it does not answer, I consider this a failure. The DNS 4.2.2.1 seems to almost always answer. Based on my results so far, I think that this tool can show you the best DNS to use. There is some blocking while the DNS results are received, and so my next projects with the socket will try asynchronous sockets.

History

28 Mar 2007 - Updated source download

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Ireland Ireland
My first experiences with computing was with a Bendix G15 drum computer at Carnegie Mellon. More followed with CDC G20, IBM 360, Univac 1108, Apple II, and 386XXX. I have done microprocessor programming and design for 6502, Z80, and 8051. I have moved to C# now and am still struggling to understand this. My career has been in engineering starting with Texas Instruments and continuing with Becton Dickinson, Dataproducts, Hitachi Printing Solutions and now retired from Ricoh Printing Systems Europe.

Comments and Discussions

 
QuestionKeeping it Simple Pin
xkxhx118-Dec-12 22:17
xkxhx118-Dec-12 22:17 
GeneralExcel Analysis Pin
ebloch16-Jul-09 9:06
ebloch16-Jul-09 9:06 
GeneralRe: Excel Analysis Pin
Charles Putney17-Jul-09 6:59
Charles Putney17-Jul-09 6:59 
GeneralRe: Excel Analysis Pin
ebloch17-Jul-09 10:48
ebloch17-Jul-09 10:48 
GeneralRe: Excel Analysis Pin
dbjohnson212-Dec-09 14:39
dbjohnson212-Dec-09 14:39 
GeneralRe: Excel Analysis Pin
Charles Putney12-Dec-09 22:30
Charles Putney12-Dec-09 22:30 
GeneralRe: Excel Analysis Pin
dbjohnson213-Dec-09 5:21
dbjohnson213-Dec-09 5:21 
GeneralA great tool - thank you Pin
Mark Dods13-Jul-09 16:02
Mark Dods13-Jul-09 16:02 
QuestionCan you change the 5 second timeout? Pin
MikeBlyth18-Dec-08 3:04
MikeBlyth18-Dec-08 3:04 
AnswerRe: Can you change the 5 second timeout? Pin
Charles Putney24-Dec-08 2:57
Charles Putney24-Dec-08 2:57 
GeneralGreat tool, something i've been looking for but never found. Pin
asdkasd12-Jul-08 3:40
asdkasd12-Jul-08 3:40 
QuestionDNStester +NT4? Yes or No? Pin
Shawn McClelland16-Jun-08 9:47
Shawn McClelland16-Jun-08 9:47 
AnswerRe: DNStester +NT4? Yes or No? Pin
Charles Putney16-Jun-08 21:21
Charles Putney16-Jun-08 21:21 
QuestionHow to resolve subdomains Pin
bas0070117-Oct-07 5:30
bas0070117-Oct-07 5:30 
AnswerRe: How to resolve subdomains Pin
Member 1480861115-May-20 4:57
Member 1480861115-May-20 4:57 
QuestionWere can i find the defined DNS Server? Pin
Fan Feng3-Sep-07 20:16
Fan Feng3-Sep-07 20:16 
AnswerRe: Were can i find the defined DNS Server? Pin
Charles Putney6-Sep-07 21:18
Charles Putney6-Sep-07 21:18 
GeneralRe: Were can i find the defined DNS Server? Pin
Fan Feng6-Sep-07 22:22
Fan Feng6-Sep-07 22:22 
Generalgracias :) Pin
fgonzaro72-May-07 12:08
fgonzaro72-May-07 12:08 
GeneralRe: gracias :) Pin
Charles Putney3-May-07 10:47
Charles Putney3-May-07 10:47 
Generaltesting domains other than .com Pin
Paul Betteridge26-Apr-07 0:36
Paul Betteridge26-Apr-07 0:36 
AnswerRe: testing domains other than .com Pin
Charles Putney3-May-07 10:37
Charles Putney3-May-07 10:37 
In the dnstester.cs line:
Regex Dotcom = new Regex("[.]([A-Za-z]*)[.]com");
is looking for web addresses on the Google page to make the random test. You could change this to .co.uk, but there will probably not be many .co.uk compared to .com

You should also know I compiled this on 2003 c# and some of the library calls are now deprecated in 2005 c#.


GeneralRe: testing domains other than .com Pin
Paul Betteridge3-May-07 22:06
Paul Betteridge3-May-07 22:06 
GeneralRe: testing domains other than .com Pin
Charles Putney4-May-07 1:46
Charles Putney4-May-07 1:46 
Generalbuild error Pin
ipsection27-Mar-07 3:19
ipsection27-Mar-07 3:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.