
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;
PingOptions options = new PingOptions(128, true);
Ping ping = new Ping();
byte[] data = new byte[32];
int received = 0;
List<long> responseTimes = new List<long>();
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");
}
}
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();
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