# Thursday, September 3, 2009

Recently, I was asked to automate the process of checking a set of known URLs and determining if each URL corresponded to a “live” site. For our purposes, a site is live if I can PING it and get a reply back.

I can open a command prompt and use the PING command and read the response to determine if a site is live. A live site would return a series of messages starting with “Reply from”, while a non-existent site would report an error.

Unfortunately it is difficult to automate this task from the command prompt. Fortunately, the .Net framework provides the tools to allow me to ping a URL with just a few lines of code. The functionality I need is in the System.Net.NetworkInformation namespace.

I have created a public class  PingUtils and added the statement

using System.Net.NetworkInformation;

at the top of this class.

Next, I added the following method to attempt to ping a URL and return true, if successful.

public bool UrlIsLive(string url, int timeOut)
{
    bool pingSuccess = false;
    Ping ping = new Ping();
    string pingData = "TEST";
    byte[] pingDataBytes = Encoding.ASCII.GetBytes(pingData);
    try
    {
        PingReply reply = ping.Send(url, timeOut, pingDataBytes);
        if (reply.Status == IPStatus.Success)
        {
            pingSuccess = true;
        }
    }
    catch(PingException)
    {
        pingSuccess = false;    
    }
    return pingSuccess;
}

That’s it. If an error occurs when I try to ping, it is most likely a PingException, which is equivalent to the "Ping request could not find host" error reported at the command prompt.

This function returns true for a URL that exists and is live; and false for one that does not exist.

The following unit tests should deomonstrate this

/// <summary>
///A positive test for IsLive
///</summary>
[TestMethod()]
public void IsLive_PingGoodUrl_ShouldReturnTrue()
{
    PingUtils pu = new PingUtils();
    string url = @"DavidGiard.com";
    int timeOut = 1000;
    bool siteIsLive = pu.UrlIsLive(url, timeOut);
    Assert.IsTrue(siteIsLive, "PingUtils.IsLive did not return true as expected");
}

/// <summary>
///A negative test for IsLive
///</summary>
[TestMethod()]
public void IsLive_PingBadUrl_ShouldReturnFalse()
{
    PingUtils pu = new PingUtils();
    string url = @"notDavidGiard.com";
    int timeOut = 1000;
    bool siteIsLive = pu.UrlIsLive(url, timeOut);
    Assert.IsFalse (siteIsLive, "PingUtils.IsLive did not return false as expected");
}

It’s worth pointing out a couple limitations of this function.

  • Some site’s reject all PING request as a way to protect themselves against Denial of Service attacks. For example, if you PING Microsoft.com, it will not Reply, even though the site does exist.
  • As with any program that uses networking, the internal firewall rules where the program runs may affect the success of the program.
  • The PING command checks for valid URLs, even if the URL returns an error page. So, foo.DavidGiard will reply to a PING request because my hosting provider redirects this to an error page.

Even given those limitations, this can be a very useful function for testing if all the Links stored in your database are still relevant.

You can download the code here.

Monday, September 7, 2009 5:35:45 PM (GMT Daylight Time, UTC+01:00)
What about using HTTP status codes to respond instead of PINGs that can be disabled and filtered via firewalls

public bool UrlIsLive()
{
bool pingSuccess = false;
string url = @"http://DavidGiard.com/";

try
{
// prepare the web page we will be asking for
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

if (response.StatusCode == HttpStatusCode.OK)
pingSuccess = true;
}
catch
{
pingSuccess = false;
}
return pingSuccess;
}
Shane Jordan
Tuesday, September 8, 2009 8:44:31 PM (GMT Daylight Time, UTC+01:00)
Thanks. Shane. I like the simplicity of your approach.
Comments are closed.