编写自己的PING工具

编写自己的PING工具
aspcool 转载   www.ASPCool.com 时间:2001-4-11 10:00:25  阅读次数:2235

     编写自己的PING工具
  
  导 读:PING 是一个用来检测网络连接速度的使用工具,下面的文章将介绍在C#中利用System.Net.Sockets 来创建一个自己的PING 工具。
  --------------------------------------------------------------------------------
  PING 是一个用来检测网络连接速度的工具,它会在本机和给出的远程主机名之间建立一个SOCKET 连接并向其发送一个ICMP协议格式的数据包,然后远程主机作出响应,发回一个数据包,通过计算发送到接收数据包的时间间隔,我们可以确定连接的速度。
  
  使用方法 ping <hostname> [/r]
  <hostname> 主机名
  [/r] 可选属性,决定是否连续的 ping 远程主机。
  
  下面是代码:
  ///ping.cs
  namespace SaurabhPing
  {
   using System;
   using System.Net;
   using System.Net.Sockets;
   /// <summary>
   /// 主要的类:ping
   /// </summary>
   class Ping
   {
   //声明几个常量
   const int SOCKET_ERROR = -1;
   const int ICMP_ECHO = 8;
   /// <summary>
   /// 这里取得Hostname参数
   /// </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>
   /// 主要的方法,用来取得IP,
   /// 并计算响应时间
   /// </summary>
   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 < 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
  }
  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值