Thursday, October 23, 2008

C# - The Ping Utility

Welcome to Learn C# - the easy way , by Saurabh Nandu.

Ping is a very useful utility used to determine the speed of a Network Connection. It establishes a socket connection with the given hostname and sends a Data Packet using ICMP Protocol. The Host then in reply send back a 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.

Usage:
Ping /r
where :
- is the Host Address of the Server to Ping
/r - Optional Switch to ping continuously to the HostName


Code:
1) Ping.cs :- The Ping Utility

namespace SaurabhPing {   using System;   using System.Net;   using System.Net.Sockets;   ///    ///		The Main Ping Class   ///    class Ping   {     //Declare some Constant Variables     const int SOCKET_ERROR = -1;             const int ICMP_ECHO = 8;     ///      ///		The Starting Point of the Class     ///		It Takes the Hostname parameter     ///      public static void Main(string[] argv)     {       if(argv.Length==0)       { 	//If user did not enter any Parameter inform him 	Console.WriteLine("Usage:Ping  /r") ; 	Console.WriteLine(" 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") ;         }      } 		       ///        ///		This method takes the "hostname" of the server       ///		and then it ping's it and shows the response time       ///        public static void PingHost(string host)       { 	//Declare the IPHostEntry  	IPHostEntry serverHE, fromHE; 	int nBytes = 0; 	int dwStart = 0, dwStop = 0; 	//Initilize 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]; 	//Initilize the Packet.Data 	for (int i = 0; i < color="#0000cc">//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 < color="#0000cc">//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();            }       ///        ///  This method get the Packet and calculates the total size        ///  of the Pack by converting it to byte array       ///        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;       }       ///        ///		This Method has the algorithm to make a checksum        ///        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     ///      ///		Class that holds the Pack information     ///      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 }

No comments:

Your Title