Building Network Utilities

Published 31 October 06 11:35 AM | Coding4Fun 
  This is a simple utility that will look for devices on the network.
3 Leaf Development

Difficulty: Easy
Time Required: 1-3 hours
Cost: Free
Software: Visual Studio Express Editions
Hardware:
 
Source Code: Missing!  But check out this article which shows off how to do network discovery using simular methods.

     

    For this first post, I've decided to dig into the new System.Net.NetworkInformation namespace, and build a simple utility that will look for devices on the network:

    This gave me the opportunity to explore a number of new features in Visual Studio 2005 by using Visual C# Express Edition. Depending on the language I wanted, I could have used any of the Visual Studio Express Editions for this sample. Beta 2 of the Express editions can be downloaded from http://msdn.microsoft.com/express.  

    The core of this application is the new Ping class (System.Net.NetworkInformation.Ping).  This gives you built-in functionality for sending an ICMP echo request to a network device.

    Visual C#

    IPAddress ip = IPAddress.Parse("192.168.1.1");
    Ping ping = new Ping();
    PingReply pr = ping.Send(ip);

    Visual Basic

    IPAddress ip = IPAddress.Parse("192.168.1.1")
    Dim newPing As Ping = New Ping()
    Dim pr As PingReply = newPing.Send(ip)

    You can see that the .NET Framework 2.0 makes it trivial to ping a network device.  Prior to the .NET Framework 2.0, it was substantially more code to accomplish this.

    In addition, I wanted to make this asynchronous so that the pings were being done in the background, and the UI was not blocked, and updated as the results came in.  Also, because there could potentially be a very large number of IP addresses, I didn't want to fire off pings for all of them at the same time.  For my testing, having about 200 pings going at the same time worked well.

    Letting 200 pings go at one time turned out to be trivial to perform using the semaphore class.  Here's how it works:

    First, you declare the semaphore class with the maximum number of threads you want to allow.  In this case that's 200:

    Visual C#

    const int THREAD_COUNT = 200;
    private Semaphore pingBlock = new Semaphore(0, THREAD_COUNT);
    pingBlock.Release(THREAD_COUNT);

    Visual Basic

    const int THREAD_COUNT = 200;
    private Semaphore pingBlock = new Semaphore(0, THREAD_COUNT);
    pingBlock.Release(THREAD_COUNT);

    Now, when the application wants to spawn a new thread to perform a ping, it uses the semaphore to insure that there aren't already 200 pings running.  The code can do this as follows:

    Visual C#

    pingBlock.WaitOne();

    Visual Basic

    pingBlock.WaitOne()

    This call allocates an item in the semaphore.  If all 200 are already allocated, then this call will block until one of the items is released.  Once WaitOne returns, this thread is unblocked, and can perform the ping.  Once the ping has completed, the thread needs to release the semaphore object so that another thread can unblock and do its ping.  This repeats until all the pings are completed.  A semaphore object is released as follows:

    Visual C#

    pingBlock.Release();

    Visual Basic

    pingBlock.Release()

    To handle all the ping operations, I created a class called "NetScan".  To kick off a set of pings, you call the NetScan.Start method, and pass in the range of IP addresses that you want it to loop through.  NetScan handles all the background threads, and fires events when each ping has completed, and another event when all of the pings are done.  In the .NET Framework 2.0, the syntax for declaring an event is much simpler.  In the past, you had to declare a delegate, and an event.  Now, you just use the generic EventHandler<T>:

    Visual C#

    //
    // Fired when each ping completes
    //
    public event EventHandler<NetScanCompletedEventArgs> PingComplete;

    //
    // Fired when all pings complete
    //
    public event EventHandler<EventArgs> NetScanComplete;

    Visual Basic

    '
    ' Fired when each ping completes
    '
    Public Event PingComplete As EventHandler(Of NetScanCompletedEventArgs)

    '
    ' Fired when all pings complete
    '
    Public Event NetScanComplete As EventHandler(Of EventArgs)

    The syntax for raising an event remains unchanged:

    Visual C#

    NetScanComplete(this, new EventArgs());

    Visual Basic

    RaiseEvent NetScanComplete(Me, New EventArgs())

    The form can then wire up handlers to respond to these events.  When each ping completes, an event is raised that lets the user interface show the results of the ping.  When all the pings have completed, an event is raised that lets the user interface know that all the results are in.  This could have been handled with traditional event handlers, but C# 2.0 supports a new feature known as anonymous methods, and I implemented the handler with those.  Here's all the code for setting up the event handlers and kicking off the ping operations:

    Visual C#

    //
    // The NetScan will perform the pings on separate threads
    //
    NetScan ns = new NetScan();

    //
    // Event handler for when each ping completes.
    //
    ns.PingComplete += delegate(object s, NetScanCompletedEventArgs ev)
    {
    if (ev.Reply.Status == IPStatus.Success)
    {
    ListViewItem li = new ListViewItem(new string[] {
    ev.Reply.Address.ToString(),
    ev.Reply.RoundtripTime.ToString(CultureInfo.InvariantCulture)
    + " ms" });
    resultsListView.Items.Add(li);
    }
    };

    //
    // Event handler for when all pings have completed.
    //
    ns.NetScanComplete += delegate(object s, EventArgs ev)
    {
    scanButton.Enabled = true;
    };

    //
    // Disable the "Scan" button while the pings are running, and start the
    // pings.
    //
    scanButton.Enabled = false;
    ns.Start(new PingRange(startIP, endIP));

    Visual Basic

    '
    ' The NetScan will perform the pings on separate threads
    '
    Dim ns As NetScan = New NetScan()

    '
    ' Event handler for when each ping completes.
    '
    AddHandler ns.PingComplete, AddressOf PingComplete

    '
    ' Event handler for when all pings have completed.
    '
    AddHandler ns.NetScanComplete, AddressOf NetScanComplete
    '
    ' Disable the "Scan" button while the pings are running, and start the ‘
    ' pings.
    '
    scanButton.Enabled = False
    ns.Start(New PingRange(startIP, endIP))

    Private Sub PingComplete(ByVal s As Object,
    ByVal ev As NetScanCompletedEventArgs)

    If ev.Reply.Status = IPStatus.Success Then
    Dim li As ListViewItem = New ListViewItem(New String()
    {ev.Reply.Address.ToString(),
    ev.Reply.RoundtripTime.ToString(
    CultureInfo.InvariantCulture) + " ms"})
    resultsListView.Items.Add(li)
    End If
    End Sub

    Private Sub NetScanComplete(ByVal s As Object, ByVal ev As EventArgs)
    scanButton.Enabled = True
    End Sub

    You can see that the event handlers for PingComplete and NetScanComplete are just placed in-line in the method body.

    This completes the tour of this application.  You can download Visual C# 2005 Express Edition and explore this application for yourself. Get started at http://msdn.microsoft.com/express.

    Filed under: ,

    Comment Notification

    If you would like to receive an email when updates are made to this post, please register here

    Subscribe to this post's comments using RSS

    Comments

    # James Bentley said on August 31, 2007 9:28 AM:

    REALLY awsome description of using the asynch method.  I've been stuck on this for months because I didn't know how to declare the event, and microsoft doesn't have examples up for VB, only C#!

    THANKS!!!!

    Jim

    # Passerby said on October 12, 2007 1:04 PM:

    Funny, the code that can be downloaded does not reflect what you've written here.

    For example, there's no reference to the use of Semaphore anywhere.

    # GermanD said on November 20, 2007 4:46 AM:

    Why do I get this error: Error 1 "'System.Windows.Forms.Application' does not contain a definition for 'EnableRTLMirroring'" in the Program.cs class.

    Also when i scan it keeps on scanning and re-adding the found IP addresses.

    Any help would be appreciated :)

    # KevinL said on February 29, 2008 2:41 PM:

    I can't seem to download this anymore.

    Can someone tell me where I can get it?

    thanks.

    -Kevin.

    # Coding4Fun said on March 3, 2008 8:00 PM:

    @KevinL:  Thanks for the heads up, working on fixing this

    # bkatous said on March 20, 2008 3:31 PM:

    It still impossible to download, this code.

    @Coding4Fun: Another "Heads up" maybe useful.

    thank you.

    # Coding4Fun said on March 26, 2008 10:27 AM:

    @KevinL and @bkatous:  I think the source for this article may be lost forever.  Sean's 3 leaf site appears to be dead and I know that gotdotnet site was EOL'ed a few years back.

    Redoing this application doesn't appear to be that hard.  I'll put it on the list.

    Sorry!

    # Umesh said on March 27, 2008 2:16 AM:

    Hi,

       From Where i download  the source code of this application.

    # Umesh said on April 24, 2008 6:47 AM:

    How can i download the source code of this application,

    # Imjoe said on April 24, 2008 1:47 PM:

    Hi...

    I've been lookin for this everywhere on net..

    Saw that ur pretty active on this site... :)

    Could u plz upload the source code somewhere?

    # Coding4Fun said on April 24, 2008 3:00 PM:

    @Umesh:  See comment above, we'll rebulid the app.

    # Newbie said on May 7, 2008 10:42 AM:

    Thanks can't wait for the rebuild so I can get learning!

    # Newbie said on May 12, 2008 3:33 AM:

    Can't wait for the app to be rebuild so I can learn to apply the techniques!

    # Mark said on June 19, 2008 10:15 PM:

    Hi,

    I'd really love a copy of the code :-)

    THanks - Mark

    # Coding4Fun said on June 23, 2008 2:58 PM:

    @Mark attempting to track down the source, it was lost when we transitioned along with source site became deprecated.

    # jmurphy said on June 26, 2008 2:20 PM:

    To see what the Form looks like:

    http://msdn.microsoft.com/fr-fr/coding4fun/bb892860.aspx

    To see most of the code (some guy hacked it), check out the last post from Evan Mulaski on page:

    http://forums.msdn.microsoft.com/en-US/netfxnetcom/thread/6c8da3c5-5e14-4e72-af9d-40f5580ba555/

    # swetterling said on November 25, 2008 2:18 PM:

    Did anyone find the original code?

    # Coding4Fun said on November 30, 2008 2:41 PM:

    @swetterling: looking at the article, you can recreate the app from the code in the article.  I have been unsuccessful in tracking down the source code sadly.  We've taken measures to prevent these types of issues in the future however.

    # Anouar said on February 15, 2009 11:07 PM:

    Hi,

    I recreated the app from the code in  the article and in the forum and i translated this article to french. you can find the project source here : http://www.futurs-ingenieurs.webou.net/scanner-reseau/ or here http://www.box.net/shared/h9ct4hxozn

    # Gary Park said on March 7, 2009 7:01 AM:

    Hello,

    I have the original source code for this application, I downloaded when the article was first published, if you would like the source code then please let me know how I can go about getting it to you.

    Thanks

    Gary

    # Manuel Bauer said on March 24, 2009 2:08 PM:

    Hello,

    has someone a copy of the sourcecode, because I can't download it.

    Thanks.

    Manuel

    # Jens Rasch said on May 15, 2009 4:55 AM:

    I would like to know, if anyone's got the code in VB.net?

    # Coding4Fun said on May 18, 2009 4:53 PM:

    @Jens Rasch we are working on creating a new version of this.  In the process of getting posted.

    # nbrege said on June 24, 2009 1:31 PM:

    Any update on the new version?

    # Delboy said on June 29, 2009 5:40 PM:

    I want to add a button to stop the all the threads, Does anyone know how to do this?

    Thanks

    # Matt said on August 4, 2009 12:46 PM:

    I'm still looking for the source for this in VB.NET if anybody could email it to me at: 1.matt@live.co.uk

    # Coding4Fun said on August 7, 2009 10:48 AM:

    Hey guys, use this instead

    http://blogs.msdn.com/coding4fun/archive/2007/04/22/2241600.aspx

    # GilbertM said on September 6, 2009 2:49 AM:

    I've already downloaded the project into my hardrive

    when i opened it, visual basic express edition automatically converted it for me.

    I know vb6.0 it seems theres a little different in this codes

    How can i ping dead IP and show it also in the list?

    Or ping IP on a list and not by range?

    # Coding4Fun said on September 6, 2009 9:40 PM:

    @GibertM vb.net and vb6 are close but different as well.  You can make the assumption a "dead ip" would be something that doesn't return a response time.  HOWEVER, people can turn off a response to pinging so it still may be in use.

    Here you won't see successes since they code says "ev.Reply.Status == IPStatus.Success" in an if statement.  For failuress, http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ipstatus.aspx gives you a massive list of possiblities

    # Saurabh Narain Gupta said on September 7, 2009 2:39 AM:

    Please tell me  how to download the source code in c#.

    I am in urgent need of it

    saurabh9gupta@gmail.com

    # Coding4Fun said on September 7, 2009 12:43 PM:

    @Saurabh Narain Gupta, see the notice at the top, use http://blogs.msdn.com/coding4fun/archive/2007/04/22/2241600.aspx instead

    # Apple said on September 10, 2009 2:05 AM:

    Hi im new here

    what if i have lots of PC on my room and i want to know which PC is online and offline and display it on the listview, i've tried my.computer.ping(ip) but my windows got stock every time i ping each ip

    I have 20 IP to ping

    PC1 ONLINE

    PC2 OFFLINE

    up to PC20

    Note: scan every 2 seconds

    I want it also to log every dead ping which last up to 5 minutes

    # Coding4Fun said on September 10, 2009 9:02 PM:

    @Apple, i don't totally know how you set this up but I'm betting you're doing pinging on a UI thread and expecting a result.  This is causing the UI to lock up since it is just spinning.  This is where multithreaded applications come in to play and why this example used a Thread Pool.

    Try checking out this example:  http://blogs.msdn.com/coding4fun/archive/2007/04/22/2241600.aspx

    Leave a Comment

    (required) 
    (optional)
    (required) 

      
    Enter Code Here: Required

    Search

    This Blog

    Syndication

    Page view tracker