?
Solved

Convert IP address to DNS value it is slow scanning 254 devices

Posted on 2011-03-18
2
Medium Priority
?
1,806 Views
Last Modified: 2012-05-11
I'm able to ping 254 devices and get result back for their round trip time between 3-4 seconds. I'm using ThreadPool and it works great.
I have collected all devices IP addresses and keeping records of those that have gotten a round trip values and those that have failed; so I can filter out the IP address that never got back their round trip from ping.
Given a collection of set good IP address; I can collect DNS values for each IP address; I have used everything but it takes 45 secods to over 1 minute to get back some DNS values from those set of good IP addresses.

I have use this code; this is very slooooow

 IPHostEntry ipHostEntry = Dns.GetHostByAddress(IPAddress.Parse(IP));

then I use this code below; it is better at best using ThreadPool but nevertheless it takes 45 secods to 1+ minute.      

        private delegate IPHostEntry GetHostEntryHandler(string ip);
        public string ReverseDNS(string ip, int timeout) // timeout in milliseconds
        {
            try
            {
                GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry);
                IAsyncResult result = callback.BeginInvoke(ip, null, null);
                if (result.AsyncWaitHandle.WaitOne(timeout, false))
                {
                    // Received response within timeout limit
                    return callback.EndInvoke(result).HostName;
                }
                else
                {
                    // Did not receive response within timeout limit,
                    // send back IP Address instead of hostname
                    return ip;
                }
            }
            catch (Exception)
            {
                // Error occurred, send back IP Address instead of hostname
                return ip;
            }
        }
 
I run a comparison to a tool that I found Si360 scanning the same 254 devices as on my test program; SI260 took 9 seconds to get response back resolve all DNS values whenever possible.

Is it anything that I'm missing to get a faster response on converting IP address to DNS.

Your help would be much appreciated.

Regards
Calos.




0
Comment
Question by:carlostriassi
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
2 Comments
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 2000 total points
ID: 35170264
Hmm, using the code below I'm resolving 174 addresses in about 12 seconds. It looks like you're not passing a callback to BeginGetHostEntry(), just using the WaitHandle for it to finish or timeout, which means the lookups are gonna run synchronously.

Resolved 174 IP addresses in 12.8888075 seconds.
140 IP addresses successfully resolved, 34 failed.

Open in new window


For my test I ran a ping on all of my networks IP addresses and put the ones that responded to the ping in a list. Then ran the DNS lookups on just the addresses in that list. I just started'em all at once, and then waited for the completedCounter to reach the number of addresses in the list. Everytime the callback is called I incremented the counter by one.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;

class Program
{
	static long completedCounter = 0;
	static long errorCounter = 0;
	static long successCounter = 0;

	static object listLock = new object();
	static object consoleLock = new object();

	static void Main(string[] args)
	{
		// Make a list of all alive hosts in my network
		List<IPAddress> aliveHosts = new List<IPAddress>();

		Console.Write("Finding alive hosts...");

		// This just pings .1 through .254, for each network
		// 192.168.1.x, 192.168.2.x, 192.168.3.x and 192.168.4.x
		// This is my entire network, I can't make a test bigger'n this. ;)
		// Everytime a host responds to a ping, add it's address to
		// the aliveHosts list
		for (byte i = 1; i < 5; i++)
		{
			for (byte j = 1; j < 255; j++)
			{
				IPAddress ip = new IPAddress(new byte[] { 192, 168, i, j });
				ThreadPool.QueueUserWorkItem(delegate(object state)
				{
					Ping ping = new Ping();
					if (ping.Send(ip, 50).Status == IPStatus.Success)
						lock (listLock) aliveHosts.Add(ip);
					Interlocked.Increment(ref completedCounter);
					lock (consoleLock)
					{
						Console.CursorLeft = 22;
						Console.Write("{0} of 1016        ", Interlocked.Read(ref completedCounter));
					}
				});
			}
		}

		do
		{
			Thread.Sleep(0);
		} while (Interlocked.Read(ref completedCounter) < 1016);

		// Reset the completedCounter
		completedCounter = 0;

		// Start timer here to check DNS performance
		Stopwatch stopwatch = new Stopwatch();
		stopwatch.Start();

		foreach (IPAddress ip in aliveHosts) // Only do lookups for hosts that are currently up
		{
			// Call GetHostEntry asynchronously - when GetHostEntry
			// finishes our GetHostEntryCallback method will be called
			Dns.BeginGetHostEntry(ip, new AsyncCallback(GetHostEntryCallback), ip);
		}

		do
		{
			// Wait until all pending GetHostEntry's finished
			// Thread.Sleep(0) won't sleep the thread, but will yield
			// processor time if another thread needs it
			Thread.Sleep(0);
		} while (Interlocked.Read(ref completedCounter) < aliveHosts.Count);
		stopwatch.Stop();

		Console.WriteLine("Resolved {0} IP addresses in {1} seconds.", aliveHosts.Count, stopwatch.Elapsed.TotalSeconds);
		Console.WriteLine("{0} IP addresses successfully resolved, {1} failed.", successCounter, errorCounter);
		Console.ReadKey();
	}

	static void GetHostEntryCallback(IAsyncResult iar)
	{
		string hostName = null;
		try
		{
			IPHostEntry host = Dns.EndGetHostEntry(iar); // Gets the result of the asynchronous method
			hostName = host.HostName;
			Interlocked.Increment(ref successCounter);
		}
		catch (Exception ex)
		{
			hostName = ex.Message;
			Interlocked.Increment(ref errorCounter);
		}
		finally
		{
			lock (consoleLock) Console.WriteLine("{0} -> {1}", iar.AsyncState, hostName);
		}
		Interlocked.Increment(ref completedCounter); // Increment the counter everytime a lookup is done (success or failure)
		return;
	}
}

Open in new window

0
 

Author Closing Comment

by:carlostriassi
ID: 35178251
great job and thank you!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Resolve DNS query failed errors for Exchange
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month12 days, 19 hours left to enroll

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question