Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Building Network Utilities

  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: Lost!!!  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.

Tags:

Follow the Discussion

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.