You Can Take It With You, Part 2

Sign in to queue

Description

  This article is about about mobility in the .NET Framework, specifically about network awareness.
Arian Kulp's Blog

Difficulty: Easy
Time Required: 1-3 hours
Cost: Free
Software: Visual Basic or Visual C# Express Editions
Hardware:
Download:

Introduction

In my last article, I discussed mobility in .NET, and specifically power awareness. This is what can allow an application to respond to battery versus AC power, battery charge level, charge status, and estimated time remaining on battery power. If you missed the article, make sure to check it out at You Can Take It With You, Part 1.

This article continues the discussion about mobility, but focuses on network awareness. Being aware of network status can allow an application to intelligently pause and resume file transfers, switch between online and offline modes, and reduce error messages due to network failures. A well-written application needs to adapt to its operating environment, but without the proper tools, a developer is forced to revert to low-level system calls or resort to inelegant solutions to the problem.

All code for this article is available in both C# and Visual Basic using the links at the top of this page. The code is primarily for illustrative purposes, but it is all functional and might help you with your own projects. To get started with this column, you'll need a copy of Microsoft Visual Basic Express Edition or Visual C# Express Edition, both free to download. You can download either of these (and other Visual Studio Express editions) from https://msdn.microsoft.com/vstudio/express. In order to properly test the network awareness mobility features, you will need to disable your network adapter, disconnect your network cable, or deactivate your wireless card.

Working with Connectivity

Network connectivity is a system capability often taken for granted when developing applications. Most people would probably use a try/catch around any network connection code, such as transferring a file or connecting to a Web service. But what happens if the network connection breaks once the connection is established? Being able to intelligently react to this is important. Even better is to modify application behavior before actual errors occur. For instance, rather than relying on an exception when a connection cannot be made, code could simply disable entirely the option to connect when offline.

A simple way to add an online/offline indicator might be to attempt a certain connection periodically, setting a Boolean flag somewhere to indicate if it was successful. Other code sections relying on a connection could then verify this flag was set to true before using the network. An example of such code might look like this:

Visual Basic

Dim onlineFlag As Boolean =  False 

...

' Execute every few seconds on a timer
Public Sub VerifyConnection()
Try
' ATTEMPT SOME CONNECTION HERE
onlineFlag = True
Catch
onlineFlag = False
End Try
End Sub
Visual C#
bool onlineFlag = false;

...

// Execute every few seconds on a timer
public void VerifyConnection()
{
try
{
// ATTEMPT SOME CONNECTION HERE
onlineFlag = true;
}
catch
{
onlineFlag = false;
}
}

This method has several problems. For one thing, running a check on a background thread or through a Timer object causes unnecessary system overhead and could potentially impact your own application or others running on the system. For another, the service may not appreciate being hit periodically just for the purposes of your connectivity flag. Also, this uses exception handling as flow control. Though a try block doesn't carry much overhead by itself, handling the exception definitely does. Any time the connection is not available, many exceptions need to be handled. Finally, the result of this method doesn't indicate whose connection — the local computer's or the remote service's — is down.

Fortunately, with the .NET Framework 2.0, you have access to several ways to determine if the system has a network connection. The new System.Net.NetworkInformation namespace provides some great information for determining connection state and more. According to the MSDN documentation, "The System.Net.NetworkInformation namespace provides access to network traffic data, network address information, and notification of address changes for the local computer. The namespace also contains classes that implement the Ping utility. You can use Ping and related classes to check whether a computer is reachable across the network." With this information you can determine if you have a connection, maximum speed, specific adapter information, and remote host accessibility.

The sample application displays some information gleaned from classes in this namespace. As seen in Figure 1, the right side contains the "Network" section. If you read my last article, you might recognize most of this interface. I've made a few changes to the network section, so make sure to get the code accompanying this article. The application demonstrates determining general network availability, local IP address, fastest interface rate, whether or not google.com is reachable, and which interface is the most active.

Generic Episode Image

Figure 1: With a valid Internet connection

The most basic piece of functionality is determining if the network is available. It turns out that there are two simple ways to check this. The first is by checking a single method. Within the NetworkInformation namespace, the NetworkInterface object provides static methods to enumerate network adapters and to determine online status.

The GetIsNetworkAvailable method, as it sounds, simply returns a true or false indicating if at least one network adapter on the system is connected to a network. The following code snippet demonstrates the easiest way to see if the system is online:

NetworkInterface.GetIsNetworkAvailable()

Though this is simple, it may not be that useful in many situations. If you need to check the method every few seconds on a timer, you have only made a small gain from the exception handling way (although this is still an improvement). Ideally, you would like to be able to respond to online/offline changes as they occur rather than by actively checking the status. Fortunately this is possible too.

The NetworkChange object, also in the System.Net.NetworkInformation namespace, exposes two static events:

  1. NetworkAddressChanged

  2. NetworkAvailabilityChanged

As you probably guessed, the NetworkAvailabilityChanged event is the one you want. Add an event handler, and then you will be notified whenever the system goes online or offline. From there, use the IsAvailable property of the event to see what happened. Now you can update a status bar, suspend data transfers, or otherwise account for the change.

Generic Episode Image

Figure 2: Without an Internet connection (wireless disabled)

Some important factors to keep in mind: First of all, you may have a network connection, yet not be "online" in the sense of having Internet connectivity. This can be an important distinction. A network connection simply means a connection to your local network. For an intranet application (such as within a company) this may well be sufficient. If you need to verify an Internet connection, you'll need to take an extra step.

In this application, I've added support to ping a host (google.com) whenever the network availability is reported as being active. The term "ping" refers to sending a signal to another computer and waiting for a response to determine if it is available. The term harkens back to submarines and radar "pings," I believe. Referring back to earlier in the article, sending the ping causes unnecessary traffic to a Web site, so it should be used with care. You may also have other uses for pinging a host, such as determining if a database server is functioning.

You can ping a host one of two ways. The first way is easier. Simply create a System.Net.NetworkInformation.Ping object, and then call the Send method with a host name. The resultant PingReply object lets you determine if the host responded, as well as the round-trip time. The problem with this method is the delay it introduces to your application. Depending on how it is called, you may lock up your user interface each time.

The second way is to ping asynchronously. When you call a method asynchronously, the operation occurs on a different thread. This frees up your main thread so that it remains responsive. In the CheckHostReachable method below, you pass in a host name, but it returns immediately. When the ping actually completes, the p_PingCompleted event handler is invoked. After making sure that no cross-thread calls to the user interface occur (checking the InvokeRequired property), the check box can be updated accordingly. It's a little trickier than the synchronous version, but your users will thank you for it!

 Visual Basic

Private pingHandler As PingCompletedEventHandler

''' <summary>
''' Determines if a given host is reachable using ping
''' </summary>
Private Sub CheckHostReachable(ByVal host As String)

Try
Dim p As New Ping()
AddHandler p.PingCompleted, pingHandler
hostReachableCheckBox.CheckState = CheckState.Indeterminate
p.SendAsync(host, 20000, Nothing)
Catch
hostReachableCheckBox.Checked = False
End Try
End Sub

''' <summary>
''' Event handler invoked when ping is complete
''' </summary>
Sub p_PingCompleted(ByVal sender As Object, ByVal e As PingCompletedEventArgs)

If Me.InvokeRequired Then
Invoke(pingHandler, sender, e)
Return
End If

hostReachableCheckBox.CheckState = _
IIf(e.Error Is Nothing AndAlso e.Reply.Status = IPStatus.Success, _
CheckState.Checked, CheckState.Unchecked)
End Sub
Visual C#
private PingCompletedEventHandler pingHandler;

...

private void CheckHostReachable(string host)
{
try
{
System.Net.NetworkInformation.Ping p = new Ping();
p.PingCompleted += pingHandler;
hostReachableCheckBox.CheckState = CheckState.Indeterminate;
p.SendAsync(host, 20000, null);
}
catch
{
hostReachableCheckBox.Checked = false;
}
}

void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
// Make sure on the same thread as UI
if (this.InvokeRequired)
{
Invoke(pingHandler, sender, e);
return;
}

hostReachableCheckBox.CheckState =
(e.Error == null && e.Reply.Status == IPStatus.Success)?CheckState.Checked:CheckState.Unchecked;
}

Take some time to examine the rest of the code. You will also see how to enumerate the network adapters and glean interesting information such as how active they are, what type of adapter they are, names, and more. These methods are a bit longer due to the looping, formatting, and displaying of the information, but they aren't actually that complicated.

Next Steps

Now that you know how to discover information about your network adapters and connections, see how you can integrate this into your applications. No more errors when a connection fails (unless you've already confirmed that the user is online!), and you can intelligently take advantage of available speed.

Conclusion

Combined with the last article about battery and power information, you should be well on your way to mobile-enabling your applications. Make the best use of this information to provide good feedback to your users, and to make use of what is available.

Download the sample code at the top of the page, download a copy of Visual Basic or C# Express at https://msdn.microsoft.com/vstudio/express, and make your code better than ever! Adding mobility features to your applications will make them portable, and more professional than ever!

The Discussion

  • User profile image
    sai

    How do we notify the client if the server ip address changes. Client will be communicating with old ip address and will not know the new Ip address to send a message.

  • User profile image
    Clint

    @sai:  If your server is changing IPs, that could cause some issues, you may want to do a DNS entry for it so you can refer to it more generically rather than a hardcoded IP.

  • User profile image
    Alessandro

    Good article.

    I try to use the GetIsNetworkAvailable  method of the NetworkInterface class to see if there is some network connection available.

    The method fail if there is a network device connected to the computer.

    LAN not connected + Network device connected =>

    GetIsNetworkAvailable  = true.

    ???How can i test not the network device??

Add Your 2 Cents