Click here to Skip to main content
15,881,204 members
Articles / Programming Languages / C#
Article

Ping.exe replica in C# 2.0

Rate me:
Please Sign up or sign in to vote.
4.52/5 (28 votes)
3 May 2007CPOL2 min read 90.2K   1.9K   85   11
Usage example of the System.Net.NetworkInformation.Ping.

Screenshot - PingDotNet.gif

Introduction

I've been working on an application that needed to connect to a webservice and exchange information with it. So before creating the proxy object, I needed to check if there is any internet connection on the client and if the webservice address can be reached. The easiest way was to call Ping.exe using the Process class and get my information from there, but it's dirty coding calling an external application for such a basic function, not to mention the security involving a call to a system component. Back in .NET Framework 1.0 or 1.1, there was no class to provide a Ping like utility; after searching in MSDN, I discovered that in C# 2.0, there is a new namespace called System.Net.NetworkInformation that has a Ping class.
So I've made a little 170 code lines console application to familiarize myself with this new class.

Background

Using the code

The console application Main method is simple; it needs an address that is resolved by calling the DNS.GetHostEntry method. But before calling the DNS, there is a method called IsOffline that checks if the client has a valid internet connection. The IsOffline method uses the InternetGetConnectedState function from the system DLL Winnet.

Internet connection checking code:

C#
[Flags]
enum ConnectionState : int
{
    INTERNET_CONNECTION_MODEM = 0x1,
    INTERNET_CONNECTION_LAN = 0x2,
    INTERNET_CONNECTION_PROXY = 0x4,
    INTERNET_RAS_INSTALLED = 0x10,
    INTERNET_CONNECTION_OFFLINE = 0x20,
    INTERNET_CONNECTION_CONFIGURED = 0x40
}

[DllImport("wininet", CharSet = CharSet.Auto)]
static extern bool InternetGetConnectedState(ref ConnectionState lpdwFlags, 
                                             int dwReserved);

static bool IsOffline()
{
    ConnectionState state = 0;
    InternetGetConnectedState(ref state, 0);
    if (((int)ConnectionState.INTERNET_CONNECTION_OFFLINE & (int)state) != 0)
    {
        return true;
    }

    return false;
}

The ping is made by a thread that calls the StartPing method:

C#
static void StartPing(object argument)
{
    IPAddress ip = (IPAddress)argument;

    //set options ttl=128 and no fragmentation
    PingOptions options = new PingOptions(128, true);

    //create a Ping object
    Ping ping = new Ping();

    //32 empty bytes buffer
    byte[] data = new byte[32];

    int received = 0;
    List<long> responseTimes = new List<long>();

    //ping 4 times
    for (int i = 0; i < 4; i++)
    {
        PingReply reply = ping.Send(ip, 1000, data, options);

        if (reply != null)
        {
            switch (reply.Status)
            {
                case IPStatus.Success:
                    Console.WriteLine("Reply from {0}: " + 
                        "bytes={1} time={2}ms TTL={3}",
                        reply.Address, reply.Buffer.Length, 
                        reply.RoundtripTime, reply.Options.Ttl);
                    received++;
                    responseTimes.Add(reply.RoundtripTime);
                    break;
                case IPStatus.TimedOut:
                    Console.WriteLine("Request timed out.");
                    break;
                default:
                    Console.WriteLine("Ping failed {0}", 
                                      reply.Status.ToString());
                    break;
            }
        }
        else
        {
            Console.WriteLine("Ping failed for an unknown reason");
        }
    }

    //statistics calculations
    long averageTime = -1;
    long minimumTime = 0;
    long maximumTime = 0;

    for (int i = 0; i < responseTimes.Count; i++)
    {
        if (i == 0)
        {
            minimumTime = responseTimes[i];
            maximumTime = responseTimes[i];
        }
        else
        {
            if (responseTimes[i] > maximumTime)
            {
                maximumTime = responseTimes[i];
            }
            if (responseTimes[i] < minimumTime)
            {
                minimumTime = responseTimes[i];
            }
        }
        averageTime += responseTimes[i];
    }

    StringBuilder statistics = new StringBuilder();
    statistics.AppendFormat("Ping statistics for {0}:", ip.ToString());
    statistics.AppendLine();
    statistics.AppendFormat("   Packets: Sent = 4, " + 
        "Received = {0}, Lost = {1} <{2}% loss>,",
        received, 4 - received, Convert.ToInt32(((4 - received) * 100) / 4));
    statistics.AppendLine();
    statistics.Append("Approximate round trip times in milli-seconds:");
    statistics.AppendLine();

    //show only if loss is not 100%
    if (averageTime != -1)
    {
        statistics.AppendFormat("    Minimum = {0}ms, " + 
            "Maximum = {1}ms, Average = {2}ms",
            minimumTime, maximumTime, (long)(averageTime / received));
    }

    Console.WriteLine();
    Console.WriteLine(statistics.ToString());
    Console.WriteLine();
    Console.WriteLine("Press any key to exit.");
    Console.ReadLine();
}

The Main code checks if an address was input from the user, then validates the internet connection, resolves the address into an IP address, and starts the thread:

C#
static void Main(string[] args)
{
    string address = string.Empty;

    if (args.Length == 0)
    {
        Console.WriteLine("PingDotNet needs a host or IP address, insert one");
        address = Console.ReadLine();
        Console.WriteLine();
    }
    else
    {
        address = args[0];
    }

    if (IsOffline())
    {
        Console.WriteLine("No internet connection detected.");
        Console.WriteLine("Press any key to exit.");
        Console.ReadLine();
        return;
    }

    IPAddress ip = null;
    try
    {
        ip = Dns.GetHostEntry(address).AddressList[0];
    }
    catch (System.Net.Sockets.SocketException ex)
    {
        Console.WriteLine("DNS Error: {0}", ex.Message);
        Console.WriteLine("Press any key to exit.");
        Console.ReadLine();
        return;
    }

    Console.WriteLine("Pinging {0} [{1}] with 32 bytes of data:", 
                      address, ip.ToString());
    Console.WriteLine();
    Thread pingThread = new Thread(new ParameterizedThreadStart(StartPing));
    pingThread.Start(ip);
    pingThread.Join();
} 

This is it. If you have any questions or suggestions, please don't hesitate to post them.

History

  • Version 1.0 - 3 May 2007

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO VeriTech.io
Romania Romania
Co-Founder at VeriTech.io. Passionate about software architecture, SOA, domain driven design, continuous integration, .NET and Javascript programming. I write on www.stefanprodan.com.

Comments and Discussions

 
GeneralYour Work helped me Pin
Kazi.Sabbir9-Jul-09 7:58
Kazi.Sabbir9-Jul-09 7:58 
Questionping an IP with a port specified Pin
Yashar Mortazavi25-Dec-08 21:20
Yashar Mortazavi25-Dec-08 21:20 
Generalping/database Pin
Member 154183817-Jun-08 0:01
Member 154183817-Jun-08 0:01 
GeneralStrange behavior Pin
BobilProject4-Jun-07 6:21
BobilProject4-Jun-07 6:21 
QuestionRe: Strange behavior Pin
Stefan Prodan4-Jun-07 6:56
Stefan Prodan4-Jun-07 6:56 
AnswerRe: Strange behavior Pin
BobilProject4-Jun-07 21:15
BobilProject4-Jun-07 21:15 
GeneralRe: Strange behavior Pin
joeraghu5-Sep-07 20:56
joeraghu5-Sep-07 20:56 
GeneralRe: Strange behavior Pin
BobilProject5-Sep-07 21:37
BobilProject5-Sep-07 21:37 
GeneralGreat work! Pin
Andrei Ion Rînea8-May-07 23:46
Andrei Ion Rînea8-May-07 23:46 
GeneralRe: Great work! Pin
Stefan Prodan9-May-07 11:31
Stefan Prodan9-May-07 11:31 
GeneralCode in C++ Pin
nobiz8-May-07 18:52
nobiz8-May-07 18:52 

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

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