Click here to Skip to main content
15,892,480 members
Articles / Programming Languages / C#

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 258.1K   7.1K   69  
Check the response times of your DNS and compare with other servers.
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Diagnostics;


namespace dnstester
{
	// Charles Putney
	// 18 Quinns Road
	// Co. Dublin
	// Ireland
	//
	// This file and the code contained within is freeware and may be
	// distributed and edited without restriction.
		// 
	// 
	public class DNSTester : System.Windows.Forms.Form
	{
		
		private System.Windows.Forms.TextBox DNSBox1;
		private System.Windows.Forms.TextBox DNSBox2;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Button Testbutton;
		private System.Windows.Forms.ListView ResultView;
		private System.Windows.Forms.ColumnHeader DNS1Timing;
		private System.Windows.Forms.ColumnHeader DNS2Timing;
		private System.Windows.Forms.ColumnHeader WebName;
		private System.Windows.Forms.ListBox StatusBox;
		private System.Windows.Forms.Label label5;
		private System.Windows.Forms.ColumnHeader DNS1IP;
		private System.Windows.Forms.ColumnHeader DNS2IP;
		private System.Windows.Forms.TextBox HTTPProxyBox;
		private System.Windows.Forms.Label label6;
		
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public DNSTester()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
				
	

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.DNSBox1 = new System.Windows.Forms.TextBox();
			this.DNSBox2 = new System.Windows.Forms.TextBox();
			this.Testbutton = new System.Windows.Forms.Button();
			this.ResultView = new System.Windows.Forms.ListView();
			this.WebName = new System.Windows.Forms.ColumnHeader();
			this.DNS1IP = new System.Windows.Forms.ColumnHeader();
			this.DNS1Timing = new System.Windows.Forms.ColumnHeader();
			this.DNS2IP = new System.Windows.Forms.ColumnHeader();
			this.DNS2Timing = new System.Windows.Forms.ColumnHeader();
			this.StatusBox = new System.Windows.Forms.ListBox();
			this.HTTPProxyBox = new System.Windows.Forms.TextBox();
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.label5 = new System.Windows.Forms.Label();
			this.label6 = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// DNSBox1
			// 
			this.DNSBox1.Location = new System.Drawing.Point(96, 40);
			this.DNSBox1.Name = "DNSBox1";
			this.DNSBox1.TabIndex = 12;
			this.DNSBox1.Text = "4.2.2.1";
			this.DNSBox1.TextChanged += new System.EventHandler(this.DNSBox1_TextChanged);
			// 
			// DNSBox2
			// 
			this.DNSBox2.Location = new System.Drawing.Point(292, 40);
			this.DNSBox2.Name = "DNSBox2";
			this.DNSBox2.TabIndex = 1;
			this.DNSBox2.Text = "152.158.16.48";
			this.DNSBox2.TextChanged += new System.EventHandler(this.DNSBox2_TextChanged);
			// 
			// Testbutton
			// 
			this.Testbutton.Location = new System.Drawing.Point(632, 24);
			this.Testbutton.Name = "Testbutton";
			this.Testbutton.TabIndex = 4;
			this.Testbutton.Text = "Test";
			this.Testbutton.Click += new System.EventHandler(this.Testbutton_Click);
			// 
			// ResultView
			// 
			this.ResultView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
																						 this.WebName,
																						 this.DNS1IP,
																						 this.DNS1Timing,
																						 this.DNS2IP,
																						 this.DNS2Timing});
			this.ResultView.GridLines = true;
			this.ResultView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
			this.ResultView.Location = new System.Drawing.Point(56, 80);
			this.ResultView.MultiSelect = false;
			this.ResultView.Name = "ResultView";
			this.ResultView.Size = new System.Drawing.Size(700, 344);
			this.ResultView.TabIndex = 11;
			this.ResultView.View = System.Windows.Forms.View.Details;
			// 
			// WebName
			// 
			this.WebName.Text = "                  URL";
			this.WebName.Width = 160;
			// 
			// DNS1IP
			// 
			this.DNS1IP.Text = "IP Address from DNS 1";
			this.DNS1IP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
			this.DNS1IP.Width = 140;
			// 
			// DNS1Timing
			// 
			this.DNS1Timing.Text = "DNS 1 Timing";
			this.DNS1Timing.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
			this.DNS1Timing.Width = 120;
			// 
			// DNS2IP
			// 
			this.DNS2IP.Text = "IP Address from DNS 2";
			this.DNS2IP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
			this.DNS2IP.Width = 140;
			// 
			// DNS2Timing
			// 
			this.DNS2Timing.Text = "DNS 2 Timing";
			this.DNS2Timing.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
			this.DNS2Timing.Width = 120;
			// 
			// StatusBox
			// 
			this.StatusBox.HorizontalScrollbar = true;
			this.StatusBox.Location = new System.Drawing.Point(80, 456);
			this.StatusBox.Name = "StatusBox";
			this.StatusBox.Size = new System.Drawing.Size(616, 95);
			this.StatusBox.TabIndex = 13;
			// 
			// HTTPProxyBox
			// 
			this.HTTPProxyBox.Location = new System.Drawing.Point(488, 40);
			this.HTTPProxyBox.Name = "HTTPProxyBox";
			this.HTTPProxyBox.TabIndex = 15;
			this.HTTPProxyBox.Text = "";
			this.HTTPProxyBox.TextChanged += new System.EventHandler(this.HTTPProxyBox_TextChanged);
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(96, 16);
			this.label1.Name = "label1";
			this.label1.TabIndex = 2;
			this.label1.Text = "DNS 1";
			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(288, 16);
			this.label2.Name = "label2";
			this.label2.TabIndex = 3;
			this.label2.Text = "DNS 2";
			this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			// 
			// label5
			// 
			this.label5.Location = new System.Drawing.Point(16, 488);
			this.label5.Name = "label5";
			this.label5.Size = new System.Drawing.Size(56, 24);
			this.label5.TabIndex = 14;
			this.label5.Text = "Status";
			// 
			// label6
			// 
			this.label6.Location = new System.Drawing.Point(488, 16);
			this.label6.Name = "label6";
			this.label6.TabIndex = 16;
			this.label6.Text = "HTTP Proxy";
			this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			// 
			// DNSTester
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(792, 573);
			this.Controls.Add(this.HTTPProxyBox);
			this.Controls.Add(this.DNSBox1);
			this.Controls.Add(this.DNSBox2);
			this.Controls.Add(this.StatusBox);
			this.Controls.Add(this.ResultView);
			this.Controls.Add(this.Testbutton);
			this.Controls.Add(this.label1);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.label5);
			this.Controls.Add(this.label6);
			this.Name = "DNSTester";
			this.Text = "DNS Tester";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		/// 
		public string DNS1,DNS2;
		public ListViewItem listURL = new ListViewItem();
		public ListViewItem.ListViewSubItem listDNS1IP = new ListViewItem.ListViewSubItem();		
		public ListViewItem.ListViewSubItem listDNS1time = new ListViewItem.ListViewSubItem();	
		public ListViewItem.ListViewSubItem listDNS2IP = new ListViewItem.ListViewSubItem();		
		public ListViewItem.ListViewSubItem listDNS2time = new ListViewItem.ListViewSubItem();

				
		

		[STAThread]
		
		static void Main() 
		{
			Application.Run(new DNSTester());
		}

		
		private void Testbutton_Click(object sender, System.EventArgs e)
		{
			int i;
			string[] CleanNames = new string[500];
			int CleanNamesCount=0;
		
			DNS1=DNSBox1.Text;
			DNS2=DNSBox2.Text;
			
			ResultView.Items.Clear();
			ResultView.Update();
			Application.DoEvents();


			GetWebAddresses(ref CleanNames,ref CleanNamesCount);

			for (i=0;i<CleanNamesCount;i++)
			{	
				ListViewItem listURL = new ListViewItem(CleanNames[i]);
				listURL.SubItems.Add(" ");
				listURL.SubItems.Add(" ");
				listURL.SubItems.Add(" ");
				listURL.SubItems.Add(" ");

				ResultView.Items.Add(listURL);
			}
				ResultView.EnsureVisible(ResultView.Items.Count-1);
		
				ResultView.Update();
				Application.DoEvents();
				
				CheckDNS(CleanNames,CleanNamesCount,DNS1,DNS2);
				
		}

		private void GetWebAddresses(ref string[] CleanNames, ref int CleanNamesCount)
		{
			int i,j;
			byte[] random = new Byte[256];
			string Letters="";
			// Make a 3 letter random string
			
			//RNGCryptoServiceProvider is an implementation of a random number generator.
			RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
			rng.GetBytes(random); // The array is now filled with cryptographically strong 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;
			}
		
			// Use Google to get random addresses for DNS testing

			// Initialize the WebRequest.
			StatusBoxPrint("Web Proxy set to: " + HTTPProxyBox.Text);
			StatusBoxPrint("Getting Google request");
			try
			{
				WebRequest GoogleRequest = WebRequest.Create("http://www.google.com/search?num=100&q="+Letters); //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();
				Application.DoEvents();

				// find all .xxx.com addresses
				MatchCollection HostNames;
				string[] Names = new string[1000];
				// Create a new Regex object and define the regular expression.
				Regex Dotcom = new Regex("[.]([A-Za-z]*)[.]com"); 
				// Use the Matches method to find all matches in the input string.
				HostNames = Dotcom.Matches(GoogleString);
				
				Application.DoEvents();
				// Loop through the match collection to retrieve all 
				// matches and delete the leading "."
				for (i = 0; i < HostNames.Count; i++) 
				{
					Names[i]= HostNames[i].Value.Remove(0,1);  
				}
				// eliminate google.com and repeated entries
				for (i=0; i<HostNames.Count-1;i++)
				{
					if (Names[i]=="google.com") Names[i]="";
					for (j=i+1;j<HostNames.Count;j++)
					{
						if (Names[i]==Names[j]) Names[j]="";
					}
				}
				// count list and compact
				j=0;
				for (i=0;i<HostNames.Count;i++)
				{
					if (Names[i] != "")
					{
						CleanNames[j]=Names[i];
						j++;
					}
				}
				CleanNamesCount=j;
				StatusBoxPrint(CleanNamesCount + " Random URL's found");
			
			}
			catch
			{
				StatusBoxPrint("Host Google.com not found - are you connected ?");
			}

		}

	
		private void CheckDNS(string[] URLNames, int URLNamescount, string DNSAddress1, string DNSAddress2)
		{
			int i;
			const int IPPort=53;
			const string TransactionID1="Q1"; // Use transaction ID of Q1 and Q2 to identify our packet and DNS
			const string TransactionID2="Q2";
			const string TypeString="\u0001"+"\u0000"+"\u0000"+"\u0001"+"\u0000"+"\u0000"+"\u0000"+"\u0000"+"\u0000"+"\u0000";
			const string TrailerString="\u0000"+"\u0000"+"\u0001"+"\u0000"+"\u0001";
			const int DNSReceiveTimeout=5000;
			string URLNameStart, DomainName, QueryString, ReceiveString, IPResponse, sDeltaTime;
			int URLNameStartLength,DomainNameLength,index, TransactionDNS;
			byte[] Sendbytes = new byte[256];
			long StartTime, StopTime;
			string DeltaTime;
			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;

			// i=0; // for testing - do one
			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);
			}
		
			byte[] Receivebytes = new byte[512];

			try
			{
				// wait for a response up to timeout
			more: DNSsocket.Receive(Receivebytes);

				
				// make sure the message returned is ours
				if (Receivebytes[0] == Sendbytes[0] && (Receivebytes[1] == 0x31) || (Receivebytes[1] == 0x32))
				{
					if (Receivebytes[2] == 0x81 && Receivebytes[3] == 0x80)
					{
						// Get the time now
						StopTime = DateTime.Now.Ticks;
						DeltaTime = Convert.ToString((double)(StopTime - StartTime)/10000000);
						
						// Decode the answers
						// Find the URL that was returned
						TransactionDNS=Receivebytes[1];
						ReceiveString = Encoding.ASCII.GetString(Receivebytes);
						index=12;
						URLNameStartLength=Receivebytes[index];
						index++;
						URLNameStart=ReceiveString.Substring(index,URLNameStartLength);
						index=index+URLNameStartLength;
						DomainNameLength=Receivebytes[index];
						index++;
						DomainName=ReceiveString.Substring(index,DomainNameLength);
						index=index+DomainNameLength;
						index=index+8;

						// Get the record type
						int ResponseType=Receivebytes[index];
						index=index+9;

						// Get the IP address if applicable
						IPResponse="";
						switch (ResponseType)
						{
							case 1: IPResponse = Convert.ToString(Receivebytes[index])+"."
										+ Convert.ToString(Receivebytes[index+1])+"."
										+ Convert.ToString(Receivebytes[index+2])+"."
										+ Convert.ToString(Receivebytes[index+3]); break;
							case 5: IPResponse = "CNAME"; break;
							case 6: IPResponse = "SOA"; break;
						}
						StatusBoxPrint("DNS Answer: "+URLNameStart+"."+DomainName+" = "+IPResponse);
				
						// Find the URL entry in the list
						for (i=0;i<ResultView.Items.Count;i++)
						{
							if (ResultView.Items[i].Text == URLNameStart+"."+DomainName)
							{	
							
								switch (TransactionDNS)
								{
									case 0x31:
										ResultView.Items[i].SubItems[1].Text=Convert.ToString(IPResponse);
										sDeltaTime=Convert.ToString(DeltaTime);
										if (sDeltaTime.Length > 5) ResultView.Items[i].SubItems[2].Text = sDeltaTime.Substring(0,5);
										else ResultView.Items[i].SubItems[2].Text = sDeltaTime;
										ResultView.Items[i].ForeColor=System.Drawing.Color.Red;
										ResultView.EnsureVisible(i);
										ResultView.Update();
										Application.DoEvents();
										ResultView.Items[i].ForeColor=System.Drawing.Color.Black;
										break;

									case 0x32:
										ResultView.Items[i].SubItems[3].Text=Convert.ToString(IPResponse);
										sDeltaTime=Convert.ToString(DeltaTime);
										if (sDeltaTime.Length > 5) ResultView.Items[i].SubItems[4].Text = sDeltaTime.Substring(0,5);
										else ResultView.Items[i].SubItems[4].Text = sDeltaTime;
										ResultView.Items[i].ForeColor=System.Drawing.Color.Red;
										ResultView.EnsureVisible(i);
										ResultView.Update();
										Application.DoEvents();
										ResultView.Items[i].ForeColor=System.Drawing.Color.Black;
										break;
								}
							}
						}
					}
					goto more;
				}
			}
			catch (SocketException e)
			{
				if (Convert.ToString(e).IndexOf("time")>0)
				{
					StatusBoxPrint("Timeout - No response received for "+ Convert.ToString (DNSReceiveTimeout/1000) + " seconds");
				}
				else
				{
					StatusBoxPrint(Convert.ToString(e)); // for testing	
				}
			}
			finally
			{
				// close the socket
				DNSsocket.Close();
			}
		
		}
	
			private void StatusBox_TextChanged(object sender, System.EventArgs e)
		{
			StatusBox.TopIndex=StatusBox.Items.Count;
			StatusBox.Update();
		}
		private void StatusBoxPrint(string LogText)
		{
			StatusBox.Items.Add(DateTime.Now+"  "+LogText);
			StatusBox.TopIndex=StatusBox.Items.Count-1;
			if (StatusBox.Items.Count > 5000)
			{
				StatusBox.Items.RemoveAt(0);
			}
			StatusBox.Update();
		}
		private void DNSAvg1Box_TextChanged(object sender, System.EventArgs e)
		{
		
		}

		private void DNSAvg2Box_TextChanged(object sender, System.EventArgs e)
		{
		
		}

		private void DNSBox1_TextChanged(object sender, System.EventArgs e)
		{
			DNS1=DNSBox1.Text;
		}

		private void DNSBox2_TextChanged(object sender, System.EventArgs e)
		{
			DNS2=DNSBox2.Text;
		}

	
		private void ResultBox_SelectedIndexChanged(object sender, System.EventArgs e)
		{
		
		}

		private void HTTPProxyBox_TextChanged(object sender, System.EventArgs e)
		{
			if (HTTPProxyBox.Text != "")
			{
				GlobalProxySelection.Select = new WebProxy(HTTPProxyBox.Text);
			}
			else
			{
				GlobalProxySelection.Select = GlobalProxySelection.GetEmptyWebProxy();
			}
		}
	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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