13

I know that I am not the first to ask the question: How do I find out if my application is online or not? I found this post: StackOverflow. I want to do it with C# and .NET 3.5.

The recommendation is to ping the resource regularly. I am not very happy with that advice. I would rather detect a network change and THEN ping my service to check if it is online.

.NET provides two events for this purpose: NetworkChange.NetworkAvailabilityChanged NetworkChange.NetworkAddressChanged

The first event sounds good but it is fired only if the last network card which is online goes offline. I have several virtual network cards which have been installed by VMWare and those are always online. The second event works but between plugging the network cable and the event, there are often 5 seconds wait time. The Windows tray icon reacts more or less immediately when I am unplugging the cable. What is the best way to be as fast as this tray icon?

My workaround would be to poll NetworkInterface.GetAllNetworkInterfaces() every 500ms and to throw my own event in case that the status of a network adapter changed.

There must be a better solution :)

Community
  • 1
  • 1
  • How do you plan on detecting all relevant network changes? There's really no way for your application to notice if some vital link is lost along the way. – Brian Rasmussen Dec 07 '09 at 13:33
  • See my edit for some new info regarding Iphlpapi.dll and NotifyAddrChange – Webleeuw Dec 07 '09 at 14:01
  • Online in what sense? With a server ? If you are online with a server, why not just send a status message every 5 seconds to determine if you are online or not? –  Dec 07 '09 at 14:43
  • When the ISP goes down there is no .NET event to fire. You really do need to ping a remote resource, and even then you only know that you have access to that remote resource. Firewalls and proxies may or may not allow access to other resources. – dotancohen Apr 11 '12 at 02:32

8 Answers8

10

I tried the link the Webleeuw suggested, but that code also needs between 4 and 10 seconds to notify me when I plug or unplug my cable. Now, I wanted to know if it just my computer or installation and I wrote my own Observer class which is based on NetworkInterface.GetAllNetworkInterfaces().

And: It works with lightning speed. My app reacts now as quickly as does the tray. The code is far from production code, it is just a quick hack. But this is what I will build upon now :)

using System;
using System.Net.NetworkInformation;
using Timer=System.Threading.Timer;

namespace NetworkCheckApp
{
public class NetworkStatusObserver
{
    public event EventHandler<EventArgs> NetworkChanged;

    private NetworkInterface[] oldInterfaces;
    private Timer timer;

    public void Start()
    {
        timer = new Timer(UpdateNetworkStatus, null, new TimeSpan(0, 0, 0, 0, 500), new TimeSpan(0, 0, 0, 0, 500));

        oldInterfaces = NetworkInterface.GetAllNetworkInterfaces();
    }

    private void UpdateNetworkStatus(object o)
    {
        var newInterfaces = NetworkInterface.GetAllNetworkInterfaces();
        bool hasChanges = false;
        if (newInterfaces.Length != oldInterfaces.Length)
        {
            hasChanges = true;
        }
        if (!hasChanges)
        {
            for (int i = 0; i < oldInterfaces.Length; i++)
            {
                if (oldInterfaces[i].Name != newInterfaces[i].Name || oldInterfaces[i].OperationalStatus != newInterfaces[i].OperationalStatus)
                {
                    hasChanges = true;
                    break;
                }
            }
        }

        oldInterfaces = newInterfaces;

        if (hasChanges)
        {
            RaiseNetworkChanged();
        }
    }

    private void RaiseNetworkChanged()
    {
        if (NetworkChanged != null)
        {
            NetworkChanged.Invoke(this, null);
        }
    }
}
}
  • 1
    A pity my edit didn't turn out to help you, but nice solution you provided yourself with :). I might use it myself in the (near) future, so thanks for providing it here. – Webleeuw Dec 07 '09 at 15:31
2

People here already told it but there is a diference between network availability and internet availability.
You can have network availability between your network interface and local router but havent internet availability between your local router and your Internet Service Provider (ISP).
There is another problem that testing by ping will tell you about internet availability but not about what network interface is providing it, i think the only way is force ping throught one interface but it isnot possible on windows.

47v1x8s7a
  • 21
  • 1
2

Try this using NetworkChange class

using System.Net.NetworkInformation

private void Form5_Load(object sender, EventArgs e)
{
    NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
}

private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
    if (e.IsAvailable)
    {
        MessageBox.Show("Available");
    }
    else
    {
        MessageBox.Show("Not available");
    }
}
Anuraj
  • 18,859
  • 7
  • 53
  • 79
  • 1
    This works only for one network. If you have several networks, the event will only be fired when all networks are offline. This is not helpful in my case (see my description) –  Dec 07 '09 at 13:54
0

Pinging your resource regularly is the only option that will give you a notification if the service goes offline, as well as if the client goes offline. Potentially you want to handle both situations.

Tim Ebenezer
  • 2,714
  • 17
  • 23
  • Yes, I know. For me, the risk that the network of a specific user is unavailable is much higher than the risk that the server is unavailable. We will ping, but not regularly but only when the application starts and when a network change occurs. Perhaps we will ping regularly but then not every 500ms :) –  Dec 07 '09 at 13:08
0

The windows tray icon is very likely connected to the network card drivers, i.e. below the operating system level which is why it can react so fast.

Since the network card is only one of many links between your client and the service that it accesses on the Internet, the only reliable way to detect whether or not the Internet is available is to poll some service out on the Internet, much the same way that ping does. In TCP/IP networking, this is known as a keepalive, and many protocols will have this built into them as an option.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
0

About the pinging: depending on how you wish to interpret the results, pinging doesn't seem watertight to me. What if the target times out once in a while, while the connection remains alive? I have yet to see the server that never fails to respond to a ping.

Checking every X millis if the network interface is still online (NetworkInterface.OperationalStatus property) seems more reliable if you'd ask me.

EDIT: This article deals with network address events on a lower level than the System.Net.NetworkInformation.NetworkChange class, or so it seems. On my pc it works very fast, so hopefully you'll be able to use that solution.

Webleeuw
  • 7,222
  • 33
  • 34
  • Thanks for the link. I had a look at it. It seems that NetworkChange is used. This is useful but I am not happy with it since it is too slow. –  Dec 07 '09 at 13:38
  • "I have yet to see the server that never fails to respond to a ping" - That's a bad assumption. Many networks drop ICMP packets. –  Dec 07 '09 at 14:44
  • @Roboto: I don't understand your comment, perhaps due to a small communication discrepancy :). With that sentence I meant to point out the fact that ping is not reliable because a server could drop one or more ping packets even if it's online. More clearly: I have yet to see the server that always and ever responds to every ping it is send. – Webleeuw Dec 07 '09 at 15:27
0

You can use ping, but I would also build a simple call to return a "yes" if it is online. That way you do know if the server is up and that it is running your code. Also I would only call or ping when a network resource is needed and not continually.

Tony Borf
  • 4,579
  • 8
  • 43
  • 51
0

Doing a ping is definitely not the cleanest option, especially if it is a web server. Some hosts will disable response to ICMP traffic, so you may ping but not get a response. How about just handling the exception gracefully when it occurs?

baldy
  • 5,524
  • 4
  • 22
  • 19
  • 1
    Well, actually I am not sending a "ping" command. Instead I am calling a webservice on my webserver. This tells me if my WCF-Services are still alive :) –  Dec 07 '09 at 14:31