I was recently tasked with putting together a ping and traceroute feature in an application and like I always do I googled to see if someone had already worked out how to do this.
I found a few people who had posted ICMP libraries and so I used one of them and tested and everything seemed to work properly. However I was getting reports that it was not working on Vista. However the person could use the built in ping and tracert utilities with no issue.
At first I thought it might be related to permissions or firewall but none of those ended up resolving the issue.
So I fired up wireshark and looked at what was different at the packet level between what I was doing and what the built in windows ping was doing.
The code I was using was returning an incorrect checksum on the ICMP reply. So I searched a bit to learn about the checksum and ended up finding somehow that as of .NET 2.0 framework there is a Ping class built into the framework!!
So I am posting this in hopes of saving someone a bunch of time with the same issue I had. Also the code I had to put together initially was much more complex. This I think you will see is very straight forward.
Download PingUtility.cs (3.14 kb)
Example Output:
Pinging 192.168.105.10 with 32 bytes of data:
Reply from 192.168.105.10: bytes=32 time=11ms TTL=128
Reply from 192.168.105.10: bytes=32 time=3ms TTL=128
Reply from 192.168.105.10: bytes=32 time=3ms TTL=128
Reply from 192.168.105.10: bytes=32 time=3ms TTL=128
Ping statistics for 192.168.105.10:
Packets: Sent = 4, Received = 4, Lost = 0
Approximate round trip times in milli-seconds:
Minimum = 3ms, Maximum = 11ms
Code:
public static string Ping()
{
using (Ping pingSender = new Ping())
{
PingOptions pingOptions = null;
StringBuilder pingResults = null;
PingReply pingReply = null;
IPAddress ipAddress = null;
int numberOfPings = 4;
int pingTimeout = 1000;
int byteSize = 32;
byte[] buffer = new byte[byteSize];
int sentPings = 0;
int receivedPings = 0;
int lostPings = 0;
long minPingResponse = 0;
long maxPingResponse = 0;
string ipAddressString = "192.168.105.10";
pingOptions = new PingOptions();
//pingOptions.DontFragment = true;
//pingOptions.Ttl = 128;
ipAddress = IPAddress.Parse(ipAddressString);
pingResults = new StringBuilder();
pingResults.AppendLine(string.Format("Pinging {0} with {1} bytes of data:", ipAddress, byteSize));
pingResults.AppendLine();
for (int i = 0; i < numberOfPings; i++)
{
sentPings++;
pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
if (pingReply.Status == IPStatus.Success)
{
pingResults.AppendLine(string.Format("Reply from {0}: bytes={1} time={2}ms TTL={3}", ipAddress, byteSize, pingReply.RoundtripTime, pingReply.Options.Ttl));
if (minPingResponse == 0)
{
minPingResponse = pingReply.RoundtripTime;
maxPingResponse = minPingResponse;
}
else if (pingReply.RoundtripTime < minPingResponse)
{
minPingResponse = pingReply.RoundtripTime;
}
else if (pingReply.RoundtripTime > maxPingResponse)
{
maxPingResponse = pingReply.RoundtripTime;
}
receivedPings++;
}
else
{
pingResults.AppendLine(pingReply.Status.ToString());
lostPings++;
}
}
pingResults.AppendLine();
pingResults.AppendLine(string.Format("Ping statistics for {0}:", ipAddress));
pingResults.AppendLine(string.Format("\tPackets: Sent = {0}, Received = {1}, Lost = {2}", sentPings, receivedPings, lostPings));
pingResults.AppendLine("Approximate round trip times in milli-seconds:");
pingResults.AppendLine(string.Format("\tMinimum = {0}ms, Maximum = {1}ms", minPingResponse, maxPingResponse));
return pingResults.ToString();
}
}