www.christopherlewis.com
Home
News
Recent Projects
Resume
Code Samples
SMTP SmartHost
SpamAssassin
Wget
Analog Reports
Feedback

If you found any of the tools on this page helpful, any donations would be appreciated.

Ping.cs RemoveURLScan_All.vbs Analog_run.vbs Logon.VBS Analog_Reports.ASP

//----------------------------------------+----------------------------------------
// Ping.cs - Ping utility written in C# and .Net similar to the classic Ping.exe
//
//     Copyright© 2002, 2003, Christopher G. Lewis - HTTP://www.ChristopherLewis.com
//
//  Supports
//    -t             Ping the specified host until stopped.
//    -a             Resolve addresses to hostnames.
//    -n count       Number of echo requests to send.
//    -l size        Send buffer size.
//    -w timeout     Timeout in milliseconds to wait for each reply.
//
//  Added code to reports ping stats.
//
//
// You might think that this is derived from Ping example by 
//   Saurabh Nandu (saurabhn@webveda.com)http://learncsharp.cjb.net  
//
//  But actually, Lance Olson of MSDN Magazine did it first
//    http://msdn.microsoft.com/msdnmag/issues/01/02/netpeers/netpeers.asp
//  and Peter A. Bromberg, Ph.D. ( pbromberg@yahoo.com) made it a web service
//    acording to http://www.eggheadcafe.com/articles/20020209.asp
//
//----------------------------------------+----------------------------------------

using System;
using System.Net;
using System.Net.Sockets;

namespace Ping
{
  /// <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[] args)
    {
      string strHostToPing = "";
      bool   bLoop = false;
      bool   bAddressResolve = false;
      int    iBytes = 32;
      uint   lngCount = 4;
      uint   lngTimeout = 1000;

      if(args.Length == 0)
      {
        //If user did not enter any Parameter inform him
        Console.WriteLine("Usage: Ping [-t] [-a] [-l size] [-n count] [-w timeout] <hostname> ") ;
        Console.WriteLine("<hostname> The name of the Host who you want to ping");
        Console.WriteLine("Options:");
        Console.WriteLine("    -t             Ping the specified host until stopped.") ;
        Console.WriteLine("    -a             Resolve addresses to hostnames.") ;
        Console.WriteLine("    -n count       Number of echo requests to send.") ;
        Console.WriteLine("    -l size        Send buffer size.") ;
        Console.WriteLine("    -w timeout     Timeout in milliseconds to wait for each reply.");
        return;
      }

      for (int iCount=0; iCount < args.Length; iCount++) 
      {
        string temp = args[iCount];
        switch (temp.ToLower()) 
        {
          case "-t":
            bLoop = true;
            break;

          case "-a":
            bAddressResolve = true;
            break;

          case "-l":
            iCount++;
            try 
            {
              //Next arg s/b an int
              iBytes = Int32.Parse(args[iCount]);
              if (iBytes < 0 | iBytes > 65500)
              {
                Console.WriteLine("Bad value for option -l, valid range is from 0 to 65500.");
                return;
              }
            }
            catch 
            {
              Console.WriteLine("Bad value for option -l, valid range is from 0 to 65500.");
              return;
            }
            break;

          case "-n":
            iCount++;
            try 
            {
              //Next arg s/b an int
              lngCount = UInt32.Parse(args[iCount]);
              if (lngCount  < 0 | lngCount  > UInt32.MaxValue)
              {
                Console.WriteLine("Bad value for option -n, valid range is from 0 to {0}.",UInt32.MaxValue);
                return;
              }
            }
            catch 
            {
              Console.WriteLine("Bad value for option -n, valid range is from 0 to {0}.",UInt32.MaxValue);
              return;
            }
            break;
            
          case "-w":
            iCount++;
            try 
            {
              //Next arg s/b an int
              lngTimeout = UInt32.Parse(args[iCount]);
              if (lngTimeout  < 1 | lngTimeout  > UInt32.MaxValue)
              {
                Console.WriteLine("Bad value for option -w, valid range is from 1 to {0}.",UInt32.MaxValue);
                return;
              }
            }
            catch 
            {
              Console.WriteLine("Bad value for option -w, valid range is from 1 to {0}.",UInt32.MaxValue);
              return;
            }
            break;
          default:
            strHostToPing = temp;
            break;
        }
      }

      //Check for continuous
      if (bLoop) lngCount = 0;

      //Do the ping
      PingHost(strHostToPing, iBytes, lngCount, lngTimeout );
    }

    /// <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 strPingHost, int iPingBytes, uint lngPingCount, uint lngPingTimeout)
    {
      const int     MAX_PACKET_SIZE = 65535;
      //Declare the IPHostEntry 
      IPHostEntry   PingTarget, PingSource;
      int           iBytesReceived = 0;
      int           dwStart = 0, dwStop = 0;
      uint          iLoop = 0;
      bool          bContinuous = false;
      //Random ICMP identification.
      // This fixes the bug where this ICMP would listen to all ICMP transmits
      Random        rndIdent = new Random();
      ushort        iIdent = (ushort) rndIdent.Next(ushort.MaxValue);

      // Get the server endpoint
      try
      {
        PingTarget = Dns.GetHostByName(strPingHost);
      }
      catch(Exception)
      {
        Console.WriteLine("Unkown host {0}" , strPingHost); // fail
        return;
      }

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

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

      Console.WriteLine("\nPinging {0} [{1}] with {2} bytes of data:\n", strPingHost, 
        ipepServer.Address.ToString(), iPingBytes);

      //check for continuous
      if (lngPingCount == 0) bContinuous = true;

      //Loop the ping
      long lngPacketsSent = 0, lngPacketsReceived = 0, lngTotalTransmitTime = 0;
      int  iMinTransmitTime = int.MaxValue, iMaxTransmitTime = int.MinValue;
      ushort iSeq = 0;
      do 
      {
        bool bReceived = false ;

        //Initialize a Socket of the Type ICMP
        Socket PingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
        //Set socket timeout, but this doesn't seem to work...
        PingSocket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, (int) lngPingTimeout);
        PingSocket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.SendTimeout, (int) lngPingTimeout);
        
        // Initialize the buffers. The receive buffer is the size of the
        // ICMP header plus the IP header (20 bytes)
        byte [] ReceiveBuffer = new byte [MAX_PACKET_SIZE];

        dwStart = System.Environment.TickCount; // Start timing
        //Gather stats
        lngPacketsSent ++;


        //Create the next packet in our sequence
        IcmpPacket PingPacket = new IcmpPacket();
        if (!GetICMPPacket(PingPacket, iIdent, iSeq++, iPingBytes) )
        {
          Console.WriteLine("Error in Making Packet");
          return;
        }
        int iPacketSize = iPingBytes + 8;
        // Move this ICMPPacket into a byte buffer
        byte [] byteSendBuffer = new byte[ iPacketSize ];
        //serialize this PingPacket into a byte array
        int iResult = 0;
        iResult = Serialize(PingPacket, byteSendBuffer, iPacketSize, iPingBytes );
        if( iResult == -1 )//if there is a error report it
        {
          Console.WriteLine("Error in Making Packet");
          return;
        }

        //send the Packet over the socket
        iResult = PingSocket.SendTo(byteSendBuffer, iPacketSize, SocketFlags.None , epServer);
        if ((iResult) == SOCKET_ERROR)
        {
          Console.WriteLine("Socket Error cannot Send Packet");
        }
        //Receive the bytes
        iBytesReceived = 0;
        //loop while waiting checking the time of the server responding 
        while(!bReceived)
        {
          try 
          {
            iBytesReceived = PingSocket.ReceiveFrom(ReceiveBuffer, MAX_PACKET_SIZE, SocketFlags.None, ref EndPointFrom);
          }
          catch //(Exception e)
          {
            //Console.WriteLine ("Request timed out. \n{0}", e.Message);
            Console.WriteLine ("Request timed out.");
            bReceived = false;
            break;
          }
          //OK, check the ident & seq
          int iTemp = ReceiveBuffer[25] * 256 + ReceiveBuffer[24];
          ushort iRecIdent = (ushort) iTemp;
          iTemp = ReceiveBuffer[27] * 256 + ReceiveBuffer[26];
          ushort iRecSeq   = (ushort) iTemp;
          if ( (iRecIdent != iIdent) || (iRecSeq != (iSeq-1)) )   //Not our packet
          {   
            Console.WriteLine ("Request timed out.");
            bReceived = false;
            break;
          }


          if (iBytesReceived == SOCKET_ERROR)
          {
            Console.WriteLine("Host not Responding") ;
            bReceived = false;
            break;
          } 
          else if (iBytesReceived > 0) 
          {

            bReceived = true;
            dwStop = System.Environment.TickCount - dwStart; // stop timing

            //Check for timeout
            if ( dwStop > lngPingTimeout)
            {
              Console.WriteLine ("Request timed out.");
              bReceived = false;
              System.Threading.Thread.Sleep(System.TimeSpan.FromMilliseconds(1000));
              break;
            }
            if (dwStop < 10) 
            {
              Console.WriteLine("Reply from {0}: bytes: {1} time:<10ms ({2})", ipepServer.Address.ToString(), iBytesReceived - 28, iRecSeq);
            } 
            else 
            {
              Console.WriteLine("Reply from {0}: bytes: {1} time: {2}ms ({3})", ipepServer.Address.ToString(), iBytesReceived - 28, dwStop, iRecSeq);
            }
            break;
          } 
        }//while

        //Gather stats
        if (bReceived) 
        {
          lngPacketsReceived++;
          lngTotalTransmitTime += dwStop;
          if (dwStop > iMaxTransmitTime) iMaxTransmitTime = dwStop;
          if (dwStop < iMinTransmitTime) iMinTransmitTime = dwStop;
        }
        iLoop++;

        if (bReceived & 
          (bContinuous | (iLoop < lngPingCount)))           //not last ping
        { 
          System.Threading.Thread.Sleep(System.TimeSpan.FromMilliseconds(1000));
        }
        //close the socket
        PingSocket.Shutdown(SocketShutdown.Both);
        PingSocket.Close();
      } while (bContinuous | (iLoop < lngPingCount));  //Do

 
      //Report stats
      Console.WriteLine("\nPing statistics for {0}", ipepServer.Address.ToString());
      if (lngPacketsSent == 0) 
      {
        Console.WriteLine("    Packets: Sent = {0}, Received = {1}, Lost = {2} ({3}% loss),", lngPacketsSent, lngPacketsReceived, lngPacketsSent-lngPacketsReceived, 0 );
      } 
      else
      {
        Console.WriteLine("    Packets: Sent = {0}, Received = {1}, Lost = {2} ({3}% loss),", lngPacketsSent, lngPacketsReceived, lngPacketsSent-lngPacketsReceived, ((double) (lngPacketsSent-lngPacketsReceived)/lngPacketsSent)* 100 );
      }
      Console.WriteLine("Approximate round trip times in milli-seconds:");
      if (lngPacketsReceived == 0) 
      {
        Console.WriteLine("    Minimum = {0}ms, Maximum =  {1}ms, Average =  {2}ms", 0, 0, 0 );
      } 
      else
      {
        Console.WriteLine("    Minimum = {0}ms, Maximum =  {1}ms, Average =  {2}ms", iMinTransmitTime, iMaxTransmitTime,(int) ((double) (lngTotalTransmitTime/lngPacketsReceived)) );
      }
      return;
    }

    
    /// <summary>
    ///  This method creates an ICMP Packet
    /// </summary>
    public static bool GetICMPPacket(IcmpPacket PingPacket, ushort Identifier, ushort SequenceNumber, int PingBytes)
    {
      int iPacketSize = 0;

      // Construct the packet to send
      PingPacket.Type = ICMP_ECHO; //8
      PingPacket.SubCode = 0; 
      PingPacket.CheckSum = UInt16.Parse("0");
      PingPacket.Identifier   = Identifier;
      PingPacket.SequenceNumber  = SequenceNumber;
      PingPacket.Data = new Byte[PingBytes];
      //Initialize the Packet.Data
      for (int iCount = 0; iCount < PingBytes; iCount++)
      {
        PingPacket.Data[iCount] = (byte)'#';
      }

      //Variable to hold the total Packet size
      iPacketSize = PingBytes + 8;
      byte [] bytPktBuffer = new byte[iPacketSize];
      int iResult = 0;

      //Call a Method Serialize which counts the total number of Bytes in the Packet
      iResult = Serialize(PingPacket, bytPktBuffer, iPacketSize, PingBytes );
      if( iResult == -1 )//Error in Packet Size
      {
        Console.WriteLine("Error in Making Packet");
        return false;
      }

      // now get this critter into a ushort array 
      ushort [] cksum_buffer = new ushort[Convert.ToInt32( Math.Ceiling( Convert.ToDouble(iResult) / 2))];
      
      //Code to initialize the ushort array 
      int icmp_header_buffer_index = 0;
      for( int iCount = 0; iCount < cksum_buffer.Length; iCount++ ) 
      {
        cksum_buffer[iCount] = BitConverter.ToUInt16(bytPktBuffer, icmp_header_buffer_index);
        icmp_header_buffer_index += 2;
      }
      //Call a method which will return a checksum and save the checksum to the Packet
      PingPacket.CheckSum = CheckSum(cksum_buffer);

      return true;
    }
    
    /// <summary>
    ///  This method is used to get the Packet and calculates the total size
    ///  of the Pack by converting it to byte array
    /// </summary>
    public static int Serialize(IcmpPacket ThisPacket, byte[] Buffer, int PacketSize, int PingData )
    {
      int cbReturn = 0;
      // serialize the struct into the array
      int iIndex = 0;

      byte [] b_type = new byte[1];
      b_type[0] = ThisPacket.Type;

      byte [] b_code = new byte[1];
      b_code[0] = ThisPacket.SubCode;

      byte [] b_cksum = BitConverter.GetBytes(ThisPacket.CheckSum);
      byte [] b_id    = BitConverter.GetBytes(ThisPacket.Identifier);
      byte [] b_seq   = BitConverter.GetBytes(ThisPacket.SequenceNumber);

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

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

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

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

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

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

      cbReturn = iIndex;
      return cbReturn;
    }
    /// <summary>
    ///   Checksum - 
    ///     Algorithm to create a checksup for a buffer
    /// </summary>
    public static ushort CheckSum( ushort[] BufferToChecksum )
    {
      int iCheckSum = 0;

      for (uint iCount = 0; iCount < BufferToChecksum.Length; iCount++) 
      {
        iCheckSum += Convert.ToInt32( BufferToChecksum[iCount] );
      }

      iCheckSum = (iCheckSum >> 16) + (iCheckSum & 0xffff);
      iCheckSum += (iCheckSum >> 16);
      return (ushort)(~iCheckSum);
    }

    /// <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 ushort   CheckSum;         // ones complement checksum of struct
      public ushort   Identifier;       // identifier
      public ushort   SequenceNumber;   // sequence number  
      public byte[]   Data;             // byte array of data
    } // class IcmpPacket  
  } // class ping
}
Send mail to Webmaster with questions or comments about this web site.
Copyright © 2003-2006 Christopher G. Lewis
Last modified: 12/30/06 by Chris Lewis
Google
speakeasy.net http://www.mersenne.org MCSD

FrontPage