君临 发表于 2015-1-5 15:36:05

C# ping 类 测试IP是否正常 IP速度 等

分享一个ping 的类大多用来测试IP是否正常 IP速度 等.
标准的ICMP报文,而不是调用CMD.

调用方法   返回string 单位(ms):
Pings p = new Pings();
string Speed = p.PingHost("127.0.0.1");


using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace VpnSec.Ro4ters
{
    class Pings
    {
      const int SOCKET_ERROR = -1;
      const int ICMP_ECHO = 8;
      public string PingHost(string host)
      {
            // 声明 IPHostEntry
            IPHostEntry ServerHE, fromHE;
            int nBytes = 0;
            int dwStart = 0, dwStop = 0;

            //初始化ICMP的Socket
            Socket socket =
             new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000);
            // 得到Server EndPoint
            try
            {
                ServerHE = Dns.GetHostByName(host);
            }
            catch (Exception)
            {

                return "没有发现主机";
            }

            // 把 Server IP_EndPoint转换成EndPoint
            IPEndPoint ipepServer = new IPEndPoint(ServerHE.AddressList, 0);
            EndPoint epServer = (ipepServer);

            // 设定客户机的接收Endpoint
            fromHE = Dns.GetHostByName(Dns.GetHostName());
            IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList, 0);
            EndPoint EndPointFrom = (ipEndPointFrom);

            int PacketSize = 0;
            IcmpPacket packet = new IcmpPacket();

            // 构建要发送的包
            packet.Type = ICMP_ECHO; //8
            packet.SubCode = 0;
            packet.CheckSum = 0;
            packet.Identifier = 45;
            packet.SequenceNumber = 0;
            int PingData = 24; // sizeof(IcmpPacket) - 8;
            packet.Data = new Byte;

            // 初始化Packet.Data
            for (int i = 0; i < PingData; i++)
            {
                packet.Data = (byte)'#';
            }

            //Variable to hold the total Packet size
            PacketSize = 32;
            Byte[] icmp_pkt_buffer = new Byte;
            Int32 Index = 0;
            //again check the packet size
            Index = Serialize(
             packet,
             icmp_pkt_buffer,
             PacketSize,
             PingData);
            //if there is a error report it
            if (Index == -1)
            {
                return "Error Creating Packet";

            }
            // convert into a UInt16 array

            //Get the Half size of the Packet
            Double double_length = Convert.ToDouble(Index);
            Double dtemp = Math.Ceiling(double_length / 2);
            int cksum_buffer_length = Index / 2;
            //Create a Byte Array
            UInt16[] cksum_buffer = new UInt16;
            //Code to initialize the Uint16 array
            int icmp_header_buffer_index = 0;
            for (int i = 0; i < cksum_buffer_length; i++)
            {
                cksum_buffer =
               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;
            //again check the packet size
            Index = Serialize(
             packet,
             sendbuf,
             PacketSize,
             PingData);
            //if there is a error report it
            if (Index == -1)
            {
                return "Error Creating Packet";

            }

            dwStart = System.Environment.TickCount; // Start timing
            //send the Packet over the socket
            if ((nBytes = socket.SendTo(sendbuf, PacketSize, 0, epServer)) == SOCKET_ERROR)
            {
                return "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;
            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, ref EndPointFrom);//, 0, SocketFlags.None, ref EndPointFrom);
                if (nBytes == SOCKET_ERROR)
                {
                  return "主机没有响应";

                }
                else if (nBytes > 0)
                {
                  dwStop = System.Environment.TickCount - dwStart; // stop timing
                  return dwStop.ToString();//"Reply from " + epServer.ToString() + " in "
                  //+ dwStop + "ms.Received: " + nBytes + " Bytes.";

                }
                timeout = System.Environment.TickCount - dwStart;
                if (timeout > 1000)
                {
                  return "超时";
                }
            }

            //close the socket
            socket.Close();
            return "";
      }
      /// <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;
            b_type = (packet.Type);

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

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

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

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

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

            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;

                cksum += buffer;
                counter += 1;
                size -= 1;
            }

            cksum = (cksum >> 16) + (cksum & 0xffff);
            cksum += (cksum >> 16);
            return (UInt16)(~cksum);
      }
    }
    /// 类结束
    /// <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;

    }
}

乔克斯 发表于 2015-1-5 15:37:19

{:3_46:}不错不错

inghot 发表于 2015-1-5 15:37:41

这个看上去好复杂的样子,估计做了完整的处理。。。

老段啦 发表于 2015-1-5 17:02:23

这个ping IP 怎么返回的都是0

style 发表于 2016-12-28 17:56:58

谢谢 分享~~~

Leo 发表于 2019-11-28 15:42:16

谢谢分享
页: [1]
查看完整版本: C# ping 类 测试IP是否正常 IP速度 等