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

Ping.exe replica in C# 2.0

By , 3 May 2007
 

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:

[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:

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:

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)

About the Author

Stefan Prodan
Technical Lead
Romania Romania
Member
I am a software architect who likes to develop under the .net framework. I am working with C# since 2004. Please visit my tech blog www.stefanprodan.eu.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralYour Work helped mememberKazi.Sabbir9 Jul '09 - 7:58 
Thanx Author,
Your Work helped me save my MSDN Reading time.
Keep good woks coming.
Questionping an IP with a port specifiedmemberYashar Mortazavi25 Dec '08 - 21:20 
googling for a sample ping code with port i'm here.
any clue?
 
regards
 
A programmer is a device for turning Tobacco and Coffee to Application Codes!

Generalping/databasememberMember 154183817 Jun '08 - 0:01 
Hi.
 
I've am working on an application that first gets all active hosts in an OU (this works fine - using SSIS) and inserts the hosts in a table in a MS SQL 2005 database.
 
I would like to ping all these hosts and then insert the result into the same table so if and host is responding it says something like "repley from + host" and if if does not answer it inserts the result like "host not responding or no dns etc + hostname".
 
Also, if I ping about 500 hosts and one of them dosent answer I get an "NO DNS press any key to continue" - is there a way to avoid that, and just keep pinging undtil it is done pinging all hosts?
 
BTW, it is a really nice piece of software you have developed.
 
You can contact me on:
 
axlrose.andersen@gmail.com
 
\Jan.
GeneralStrange behaviormemberBobilProject4 Jun '07 - 6:21 
Thanks for you're article, it helps me much in a my project.
 
There is a strange behavior, if I ping an host over internet the latency is the same as ping.exe of Windows, but if I ping an host inside my LAN I get latency of about 80 ms against 1 ms with ping.exe.
 
Any suggestion?
 
Diego
QuestionRe: Strange behaviormemberStefan Prodan4 Jun '07 - 6:56 
How do you ping in LAN using the IP or the PC name?
 
http://stefanprodan.wordpress.com

AnswerRe: Strange behaviormemberBobilProject4 Jun '07 - 21:15 
I ping with IP address
GeneralRe: Strange behaviormemberjoeraghu5 Sep '07 - 20:56 
Did u get the answer for this????????????
coz i tried to ping using ip, but i couldnt...... Frown | :(
GeneralRe: Strange behaviormemberBobilProject5 Sep '07 - 21:37 
I change "GetHostEntry" method with "Resolve" method.
Also if it is marked as obsolete seems to be more efficient for me.
 
Bye
GeneralGreat work!memberAndrei Rinea8 May '07 - 23:46 
Great work dude! / Super tare frate!
 
Smile | :)
GeneralRe: Great work!memberStefan Prodan9 May '07 - 11:31 
merci Big Grin | :-D
 
http://stefanprodan.wordpress.com

GeneralCode in C++membernobiz8 May '07 - 18:52 
Anybody have code like this in C++
 
nobiz

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 3 May 2007
Article Copyright 2007 by Stefan Prodan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid