11.7 Ping an IP Address


Problem

You want to check to see if a computer is online and gauge its response time.

Solution

Send a ping message. This message is sent using the Internet Control Message Protocol (ICMP) protocol with a raw socket.

Discussion

A ping message contacts a device at a specific IP address, sends a test message, and requests that the remote device respond by echoing back the packet. To gauge the connection latency between two computers, you can measure the time taken for a ping response to be received.

Despite the simplicity of ping messages compared to other types of network communication, implementing a ping utility in .NET requires a significant amount of complex, low-level networking code. The .NET class library doesn't have a prebuilt solution ”instead, you must use raw sockets and some exceedingly lengthy code.

However, at least one developer has solved the ping problem. Lance Olson, a developer at Microsoft, has provided C# code that allows you to ping a host by name or IP address and measure the milliseconds taken for a response. This code has been adapted into the following Pinger class (shown below with some details and error-handling code omitted). The complete code is available with this book's sample files.

 using System; using System.Net; using System.Net.Sockets; public class Pinger {     public static int GetPingTime(string host) {                  int dwStart = 0, dwStop = 0;         // Create a raw socket.         Socket socket = new Socket(AddressFamily.InterNetwork,            SocketType.Raw, ProtocolType.Icmp);         // Get the server IPEndPoint, and convert it to an EndPoint.         IPHostEntry serverHE = Dns.GetHostByName(host);         IPEndPoint ipepServer = new IPEndPoint(serverHE.AddressList[0], 0);         EndPoint epServer = (ipepServer);         // Set the receiving endpoint to the client machine.         IPHostEntry fromHE = Dns.GetHostByName(Dns.GetHostName());         IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0], 0);                 EndPoint EndPointFrom = (ipEndPointFrom);         // Construct the packet to send.         int PacketSize = 0;         IcmpPacket packet = new IcmpPacket();         for (int j = 0; j < 1; j++) {             packet.Type = ICMP_ECHO;             packet.SubCode = 0;             packet.CheckSum = UInt16.Parse("0");             packet.Identifier   = UInt16.Parse("45");              packet.SequenceNumber  = UInt16.Parse("0");              int PingData = 32;              packet.Data = new Byte[PingData];             for (int i = 0; i < PingData; i++)                 packet.Data[i] = (byte)'#';             PacketSize = PingData + 8;             Byte [] icmp_pkt_buffer = new Byte [PacketSize];              int index = 0;                       index = Serialize(packet, icmp_pkt_buffer, PacketSize, PingData);             // Calculate the checksum for the packet.             double double_length = Convert.ToDouble(index);             double dtemp = Math.Ceiling(double_length / 2);             int cksum_buffer_length = Convert.ToInt32(dtemp);             UInt16[] cksum_buffer = new UInt16[cksum_buffer_length];             int icmp_header_buffer_index = 0;             for (int i = 0; i < cksum_buffer_length; i++) {                 cksum_buffer[i] = BitConverter.ToUInt16(icmp_pkt_buffer,                    icmp_header_buffer_index);                 icmp_header_buffer_index += 2;             }             UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length);             packet.CheckSum  = u_cksum;                           // Now that we have the checksum, serialize the packet again.             byte[] sendbuf = new byte[PacketSize];              index = Serialize(packet, sendbuf, PacketSize, PingData);             // Start timing.             dwStart = System.Environment.TickCount;              socket.SendTo(sendbuf, PacketSize, 0, epServer);             // Receive the response, and then stop timing.             byte[] ReceiveBuffer = new byte[256];              socket.ReceiveFrom(ReceiveBuffer, 256, 0, ref EndPointFrom);             dwStop = System.Environment.TickCount - dwStart;         }         // Clean up and return the calculated ping time in seconds         socket.Close();              return (int)dwStop;     }     private static int Serialize(IcmpPacket packet, byte[] buffer,       int packetSize, int pingData) {         // (Private method for serializing the packet omitted.)     }     private static UInt16 checksum(UInt16[] buffer, int size) {         // (Private method for calculating the checksum omitted.)     }  } public class IcmpPacket {      public byte Type; // type of message           public byte SubCode; // type of sub code        public UInt16 CheckSum; // ones complement checksum of struct                public UInt16 Identifier; // identifier     public UInt16 SequenceNumber; // sequence number       public byte[] Data; } 

You can use the static Pinger.GetPingTime method with an IP address or a domain name. The GetPingTime method returns the number of milliseconds that elapse before a response is received. Here's the code that tests three Web sites:

 public class PingTest {     private static void Main() {         Console.WriteLine("Milliseconds to contact www.yahoo.com: " +           Pinger.GetPingTime("www.yahoo.com").ToString());         Console.WriteLine("Milliseconds to contact www.seti.org: " +           Pinger.GetPingTime("www.seti.org").ToString());         Console.WriteLine("Milliseconds to contact the local computer: " +           Pinger.GetPingTime("127.0.0.1").ToString());         Console.ReadLine();     } } 

The ping test allows you to verify that other computers are online. It can also be useful if your application needs to evaluate several different remote computers that provide the same content and determine which one will offer the lowest network latency for communication.

Note  

A ping attempt might not succeed if a firewall forbids it. For example, many heavily trafficked sites ignore ping requests because they're wary of being swamped by a flood of simultaneous pings that will tie up the server (in essence, a denial of service attack).




C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net