Master C# Logo banner
Welcome to MasterCSharp.com - Master C#, the easy way... - by Saurabh Nandu

 


Ping

Add Comment
 

 
Download File SDK
ping.zip (8kb) Beta1

Introduction
Ping is a very useful utility used to determine the speed of a Network Connection its also used in many other networking utilities. It sends a Data Packet using ICMP Protocol to the given Host. The Host then in reply sends back a Data Packet. The time taken to Send and Receive a Data Packet is calculated in Milliseconds. This helps us to know the speed of the connection.  
In this example I use the Socket class from the "System.Net.Socket" namespace.

I was on the look out for the code in C# for a long time finally I got it in the MSDN Magazine.
It was written by Lance Olson in his example Share Baby. I have changed his example to suit my needs.

Requirements
1) This example uses .NET SDK beta1 (Note: This example might not run on the future versions of the SDK)

Usage
Ping <hostname> /r
where :
<hostname> -  is the Host Address of the Server to Ping 
/r - Optional Switch to ping continuously to the Host Name

Code

1) Ping.cs :- The Ping Utility

namespace SaurabhPing
{
  using System;
  using System.Net;
  using System.Net.Sockets;
  /// <summary>
  ///  The Main Ping Class
  /// </summary>
  class Ping
  {
    //Declare some Constant Variables
    const int SOCKET_ERROR = -1;
    const int ICMP_ECHO = 8;
    /// <summary>
    ///		The Starting Point of the Class
    ///		It Takes the Hostname parameter
    /// </summary>
    public static void Main(string[] argv)
    {
      if(argv.Length==0)
      {
	//If user did not enter any Parameter inform him
	Console.WriteLine("Usage:Ping <hostname> /r") ;
  Console.WriteLine("<hostname> The name of the Host who you want to ping");
	Console.WriteLine("/r Ping the host continuously") ;
      }
      else if(argv.Length==1)
      {
	//Just the hostname provided by the user
	//call the method "PingHost" and pass the
         //HostName as a parameter
	PingHost(argv[0]) ;
      }
      else if(argv.Length==2)
      {
	//the user provided the hostname and the switch
	if(argv[1]=="/r")
	{
	  //loop the ping program
	  while(true)
	  {
		//call the method "PingHost" and pass the
		//HostName as a parameter
		PingHost(argv[0]) ;
	  }
        }
	else
	{
	  //if the user provided some other switch
	  PingHost(argv[0]) ;
	 }
       }
       else
       {
	 //Some error occurred
	 Console.WriteLine("Error in Arguments") ;
        }
     }

      /// <summary>
      ///	 This method takes the "hostname" of the server
      ///	 and then it ping's it and shows the response time
      /// </summary>
      public static void PingHost(string host)
      {
	//Declare the IPHostEntry 
	IPHostEntry serverHE, fromHE;
	int nBytes = 0;
	int dwStart = 0, dwStop = 0;
	//Initialize a Socket of the Type ICMP
	Socket socket =
new Socket(AddressFamily.AfINet,SocketType.SockRaw,ProtocolType.ProtICMP);

	// Get the server endpoint
	try
	{
	  serverHE = DNS.GetHostByName(host);
	}
	catch(Exception)
	{
	  Console.WriteLine("Host not found"); // fail
	  return ;
	}

	// Convert the server IP_EndPoint to an EndPoint
	IPEndPoint ipepServer = new IPEndPoint(serverHE.AddressList[0],0);
	EndPoint epServer = (ipepServer);

	// Set the receiving endpoint to the client machine
	fromHE = DNS.GetHostByName(DNS.GetHostName());
	IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0],0);
	EndPoint EndPointFrom = (ipEndPointFrom);

	int PacketSize = 0;
	IcmpPacket packet = new IcmpPacket();
	// Construct the packet to send
	packet.Type = ICMP_ECHO; //8
	packet.SubCode = 0;
	packet.CheckSum = UInt16.Parse("0");
	packet.Identifier   = UInt16.Parse("45");
	packet.SequenceNumber  = UInt16.Parse("0");
	int PingData = 32; // sizeof(IcmpPacket) - 8; 
	packet.Data = new Byte[PingData];
	//Initialize the Packet.Data
	for (int i = 0; i < PingData; i++)
	{
	  packet.Data[i] = (byte)'#';
	}

	//Variable to hold the total Packet size
	PacketSize = PingData + 8;
	Byte [] icmp_pkt_buffer = new Byte[ PacketSize ];
	Int32 Index = 0;
	//Call a Method Serialize which counts
	//The total number of Bytes in the Packet
	Index = Serialize(
	                  packet,
	                 icmp_pkt_buffer,
	                  PacketSize,
	                   PingData );
	//Error in Packet Size
	if( Index == -1 )
	{
	  Console.WriteLine("Error in Making Packet");
	  return ;
	}

	// now get this critter into a UInt16 array

	//Get the Half size of the Packet
	Double double_length = Convert.ToDouble(Index);
	Double dtemp = Math.Ceil( double_length / 2);
	int cksum_buffer_length = Convert.ToInt32(dtemp);
	//Create a Byte Array
	UInt16 [] cksum_buffer = new UInt16[cksum_buffer_length];
	//Code to initialize the Uint16 array 
	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;
	}
	//Call a method which will return a checksum
	UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length);
	//Save the checksum to the Packet
	packet.CheckSum  = u_cksum;

	// Now that we have the checksum, serialize the packet again
	Byte [] sendbuf = new Byte[ PacketSize ];
	//again check the packet size
	Index = Serialize(
	                  packet,
	                  sendbuf,
	                  PacketSize,
	                  PingData );
	//if there is a error report it
	if( Index == -1 )
	{
	  Console.WriteLine("Error in Making Packet");
	  return ;
	}


	dwStart = System.Environment.TickCount; // Start timing
	//send the Pack over the socket
	if ((nBytes = socket.SendTo(sendbuf, PacketSize, 0,
				epServer)) == SOCKET_ERROR)
	{
	  Console.WriteLine("Socket Error cannot Send Packet");
	}
	// Initialize the buffers. The receive buffer is the size of the
	// ICMP header plus the IP header (20 bytes)
	Byte [] ReceiveBuffer = new Byte[256];
	nBytes = 0;
	//Receive the bytes
	bool recd =false ;
	int timeout=0 ;

	//loop for checking the time of the server responding 
	while(!recd)
	{
	  nBytes = socket.ReceiveFrom(ReceiveBuffer,256,0,ref EndPointFrom);
	  if (nBytes == SOCKET_ERROR)
	  {
	    Console.WriteLine("Host not Responding") ;
	    recd=true ;
	    break;
	  }
	  else if(nBytes>0)
	  {
	    dwStop = System.Environment.TickCount - dwStart; // stop timing
	    Console.WriteLine("Reply from "+epServer.ToString()+" in "
		+dwStop+"MS :Bytes Received"+nBytes);
	    recd=true;
	    break;
	  }
	  timeout=System.Environment.TickCount - dwStart;
	  if(timeout>1000)
	  {
	    Console.WriteLine("Time Out") ;
	    recd=true;
	  }
        }

	//close the socket
	socket.Close();
      }
      /// <summary>
      ///  This method get the Packet and calculates the total size
      ///  of the Pack by converting it to byte array
      /// </summary>
      public static Int32 Serialize(IcmpPacket packet, Byte[] Buffer,
			Int32 PacketSize, Int32 PingData )
      {
	Int32 cbReturn = 0;
	// serialize the struct into the array
	int Index=0;

	Byte [] b_type = new Byte[1];
	b_type[0] = (packet.Type);

	Byte [] b_code = new Byte[1];
	b_code[0] = (packet.SubCode);

	Byte [] b_cksum = BitConverter.GetBytes(packet.CheckSum);
	Byte [] b_id = BitConverter.GetBytes(packet.Identifier);
	Byte [] b_seq = BitConverter.GetBytes(packet.SequenceNumber);

	// Console.WriteLine("Serialize type ");
	Array.Copy( b_type, 0, Buffer, Index, b_type.Length );
	Index += b_type.Length;

	// Console.WriteLine("Serialize code ");
	Array.Copy( b_code, 0, Buffer, Index, b_code.Length );
	Index += b_code.Length;

	// Console.WriteLine("Serialize cksum ");
	Array.Copy( b_cksum, 0, Buffer, Index, b_cksum.Length );
	Index += b_cksum.Length;

	// Console.WriteLine("Serialize id ");
	Array.Copy( b_id, 0, Buffer, Index, b_id.Length );
	Index += b_id.Length;

	Array.Copy( b_seq, 0, Buffer, Index, b_seq.Length );
	Index += b_seq.Length;

	// copy the data	 
	Array.Copy( packet.Data, 0, Buffer, Index, PingData );
	Index += PingData;
	if( Index != PacketSize/* sizeof(IcmpPacket)  */) {
	  cbReturn = -1;
	  return cbReturn;
	}

	cbReturn = Index;
	return cbReturn;
      }
      /// <summary>
      ///		This Method has the algorithm to make a checksum
      /// </summary>
      public static UInt16 checksum( UInt16[] buffer, int size )
      {
	Int32 cksum = 0;
	int counter;
 	counter = 0;

	while ( size > 0 ) {
          UInt16 val = buffer[counter];

	  cksum += Convert.ToInt32( buffer[counter] );
	  counter += 1;
	  size -= 1;
	}

	cksum = (cksum >> 16) + (cksum & 0xffff);
	cksum += (cksum >> 16);
	return (UInt16)(~cksum);
      }
    } // class ping
    /// <summary>
    ///		Class that holds the Pack information
    /// </summary>
    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;

     } // class IcmpPacket
}

Comments

Add Comment