Click here to Skip to main content
Click here to Skip to main content

Detect Internet Network Availability

, 12 Mar 2010
Rate this:
Please Sign up or sign in to vote.
Detect network availability, specifically to the Internet, and monitor status changes

Contents

Introduction

This article describes a small class that can be used to determine network availability and detect when changes occur in connectivity. This focuses on "Internet availability". In other words, if at least one IP related interface is available and working, then we assume the "network" is available.

Background

The iTuner lyrics engine relies on online providers to search for song lyrics. It reaches out to the Internet whenever a song that does not yet have lyrics begins playing. Requirements specific to iTuner are as follows:

  • Determine the current connectivity state
  • Subscribe to be notified when changes occur in network connectivity
  • Ignore all network adapters that probably do not provide connectivity to the Internet since my main goal was to contact Internet resources

This led to the System.Net.NetworkInformation namespace and the thin wrapper presented below. There are a couple of scenarios that these System classes do not cover and this article addresses those. Of course, you could generalize these requirements for any application or extend this class with other features such as pinging a target site to check for existence prior to heavier communication.

Using the Code

The NetworkStatus class is a static class exposing one method and one event as shown here:

public static class NetworkStatus
{
    public static event NetworkStatusChangedHandler AvailabilityChanged;
    public static bool IsAvailable { get; }
}

As you can see, there's not much to it - and that's the point.  Although there's not an immense amount of code behind this class, it encapsulates all the messiness so we don't have to worry about the details. The NetworkStatusDemo application attached to this article demonstrates the most minimal use of this class. It first reports the current network availability using the IsAvailable property.

if (NetworkStatus.IsAvailable)
{
    Console.WriteLine("... Network is available");
}
else
{
    Console.WriteLine("... Network is not available");
}

NetworkStatusDemo then attaches a NetworkStatusChangedHandler handler to the AvailabilityChanged event.

NetworkStatus.AvailabilityChanged +=
    new NetworkStatusChangedHandler(DoAvailabilityChanged);

static void DoAvailabilityChanged (
    object sender, NetworkStatusChangedArgs e)
{
    if (e.IsAvailable)
    {
        Console.WriteLine("... Network is available");
    }
    else
    {
        Console.WriteLine("... Network is not available");
    }
}

Quite simple, but it's enough to determine whether we should attempt to contact a Web site or Web service at any specific point in time.

Inside the Code

While the original .NET classes provide most of the functionality needed here, I had two primary objectives:

  1. Narrow the scope of the NetworkInterface class to only report on adapters capable of connecting to the Internet
  2. Encapsulate the multiple events offered by the NetworkChange class

System.Net.NetworkInformation.NetworkInterface

The NetworkInteface class includes the static GetIsNetworkAvailable() method. While this method already does most of the work we need, I've found there are situations, especially with wireless adapters, where the network appears to be online but has not yet established a truly open connection to the network. It also sees virtual machine adapters and thinks they are online; obviously, unless you've some strange development configuration where you're using a virtual machine as a router, these are not going to lead you to the Internet.

We begin with a quick test using GetIsNetworkAvailable but then extend that by examining each appropriate network interface for activity, BytesReceived and BytesSent. This is encapsulated in our NetworkStatus.IsNetworkAvailable() method.

private static bool IsNetworkAvailable ()
{
    // only recognizes changes related to Internet adapters
    if (NetworkInterface.GetIsNetworkAvailable())
    {
        // however, this will include all adapters
        NetworkInterface[] interfaces =
            NetworkInterface.GetAllNetworkInterfaces();

        foreach (NetworkInterface face in interfaces)
        {
            // filter so we see only Internet adapters
            if (face.OperationalStatus == OperationalStatus.Up)
            {
                if ((face.NetworkInterfaceType != NetworkInterfaceType.Tunnel) &&
                    (face.NetworkInterfaceType != NetworkInterfaceType.Loopback))
                {
                    IPv4InterfaceStatistics statistics =
                        face.GetIPv4Statistics();

                    // all testing seems to prove that once an interface
                    // comes online it has already accrued statistics for
                    // both received and sent...

                    if ((statistics.BytesReceived > 0) &&
                        (statistics.BytesSent > 0))
                    {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

While this is sufficient to test for current availability, we can optimize efficiency by maintaining a private Boolean variable, isAvailable, and setting its state only when the connectivity status changes. This is where the NetworkChange class comes into play.

System.Net.NetworkInformation.NetworkChange

The NetworkChange class has two events, NetworkAvailabilityChanged and NetworkAddressChanged. Sounds great. But the problem is that NetworkChange does not discriminate against adapters that might not grant us access to the Internet, such as tunnel adapters. So our NetworkStatus class extends this capability to include events from only relevant adapters. We manage this by tightly controlling the NetworkAvailabilityChanged and NetworkAddressChanged events ourselves, hiding them behind our own AvailabilityChanged event.

public static event NetworkStatusChangedHandler AvailabilityChanged
{
    add
    {
        if (handler == null)
        {
            NetworkChange.NetworkAvailabilityChanged
                += new NetworkAvailabilityChangedEventHandler(
                   DoNetworkAvailabilityChanged);

            NetworkChange.NetworkAddressChanged
                += new NetworkAddressChangedEventHandler(
                   DoNetworkAddressChanged);
        }

        handler = (NetworkStatusChangedHandler)Delegate.Combine(handler, value);
    }

    remove
    {
        handler = (NetworkStatusChangedHandler)Delegate.Remove(handler, value);

        if (handler == null)
        {
            NetworkChange.NetworkAvailabilityChanged
                -= new NetworkAvailabilityChangedEventHandler(
                   DoNetworkAvailabilityChanged);

            NetworkChange.NetworkAddressChanged
                -= new NetworkAddressChangedEventHandler(
                   DoNetworkAddressChanged);
        }
    }
}

You can see that we provide our own handler variable.  This is defined as an event that we can fire when we want to signal state changes to our consumers.

Unfortunately, the handlers for the two wrapped events do not have similar signatures. So we need to supply two distinct handlers. But they both funnel into a single point, SignalAvailabilityChange.

private static void SignalAvailabilityChange (object sender)
{
    bool change = IsNetworkAvailable();
    // only signal consumers when the general state changes
    if (change != isAvailable)
    {
        // set the local isAvailable variable
        isAvailable = change;
        if (handler != null)
        {
            handler(sender, new NetworkStatusChangedArgs(isAvailable));
        }
    }
}

In the end, not a lot of code and not very complicated or revolutionary. But it's proven to be a tidy implementation that helps to simplify any main application.

Conclusion

If you found this article helpful and enjoy the iTuner application, please consider donating to support continual improvements of iTuner and, hopefully, more helpful articles. Thanks!

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

stevenmcohn
Architect
United States United States
No Biography provided

Comments and Discussions

 
GeneralNetwork Connected! PinmemberRock (Multithreaded)8-Mar-14 11:12 
Questionfirewall protected internet Detection?? PinmemberMember 1054021121-Jan-14 18:19 
SuggestionA Suggestion PinmemberVekool_Coder14-Aug-13 19:11 
QuestionVMs [modified] PinmemberJrmsoft18-Jul-13 5:55 
AnswerRe: VMs Pinmemberstevenmcohn18-Jul-13 12:22 
GeneralMy vote of 5 Pinmember| B | A | N | D | I |15-Feb-13 23:54 
QuestionAre you sure ? PinmemberJasper4C#17-Mar-10 0:38 
AnswerRe: Are you sure ? Pinmemberstevenmcohn17-Mar-10 1:53 
QuestionRe: Are you sure ? PinmemberMember 1077588725-Apr-14 15:10 
GeneralNice! PinmemberMember 45586612-Mar-10 1:09 
GeneralRe: Nice! [modified] Pinmemberssepan14-Mar-10 19:22 
GeneralRe: Nice! [modified] Pinmemberstevenmcohn15-Mar-10 1:09 
GeneralRe: Nice! [modified] Pinmemberssepan15-Mar-10 5:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140709.1 | Last Updated 12 Mar 2010
Article Copyright 2010 by stevenmcohn
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid