C# ping命令的实现

namespace Cornfield
{
    using System;
    using System.Net;
    using System.Net.Sockets;

    class MyPing
    {
        public static void Main(string[] argv)
        {
            if(argv.Length==1 || argv.Length==2)
                PingHost(argv);
            else
            {
                Console.WriteLine("Invalid Command.");
                Console.WriteLine("Usage : 1. MyPing <hostname>.") ;
                Console.WriteLine("       2. MyPing <hostname> <client>.");
                string[] hao = new string[2];
                hao[1] = "localhost";
                hao[0] = "focweb_hao";
                PingHost(hao);
            }    
        }   
        public static void PingHost(string[] hostclient)
        {   
            //    1。解析地址的地址模式,较常用的为AddressFamily.InterNetwork,即IPv4地址。
            //    2。Socket套接字类型,一般为SocketType.Raw原始类型。
            //    3。网络协议类型,这里Ping用的是Internet控制报文协议ProtocolType.Icmp.  
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
          
            IPHostEntry hostInfo;
            try
            {
                hostInfo = Dns.GetHostByName(hostclient[0]);  
            }
            catch(Exception)
            {
                Console.WriteLine("Unknown host {0}.",hostclient[0]);
                return ;
            }
            // 取主机0号端口
            EndPoint hostPoint= (EndPoint)new IPEndPoint(hostInfo.AddressList[0], 0);
            IPHostEntry clientInfo;
            try
            {
                if (hostclient.Length==2)
                    clientInfo =Dns.GetHostByName(hostclient[1]);
                else
                    clientInfo = Dns.GetHostByName(Dns.GetHostName());
            }
            catch(Exception)
            {
                Console.WriteLine("Unknown client {1}.",hostclient[1]);
                return ;
            }
            // 取客户机0号端口       
            EndPoint clientPoint = (EndPoint)new IPEndPoint(clientInfo.AddressList[0], 0);      

            int DataSize = 32; // ICMP数据包大小;
            int PacketSize = DataSize + 8;//总报文长度
            const int ICMP_ECHO = 8;
            IcmpPacket packet = new IcmpPacket(ICMP_ECHO,0,0,45,0,DataSize);
                       
            Byte [] Buffer = new Byte[ PacketSize ];
            int index=packet.ConvertToByte(Buffer);
            if( index != PacketSize)
            {
              Console.WriteLine("There is something wrong with Packet Data !");
              return ;
            }

            int cksum_buffer_length =(int)Math.Ceiling( ((Double)index)/ 2);

            UInt16 [] cksum_buffer = new UInt16[cksum_buffer_length];

            int icmp_header_buffer_index = 0;
            for( int i = 0; i < cksum_buffer_length; i++ )
            {
                  cksum_buffer[i] = BitConverter.ToUInt16(Buffer,icmp_header_buffer_index);
                  icmp_header_buffer_index += 2;
            }


            packet.CheckSum =IcmpPacket.SumOfCheck(cksum_buffer);
            // 保存校验和后,再次将报文转化为数据包
            Byte [] SendData = new Byte[ PacketSize ];
            index= packet.ConvertToByte(SendData);
            if( index != PacketSize)
            {
              Console.WriteLine("There is something wrong with Packet Data !");
              return ;
            }
                          

            int nBytes=0;
            int startTime = Environment.TickCount;
            if ((nBytes = socket.SendTo(SendData, PacketSize, SocketFlags.None,(EndPoint) hostPoint)) == -1)
            {      
              Console.WriteLine("Socket can not send packet");
            }


            Byte [] ReceiveData = new Byte[256];   
            nBytes = 0;

            int timeout=0 ;
            int timeConsume=0;

            while(true)
            {
                nBytes = socket.ReceiveFrom(ReceiveData, 256,SocketFlags.None,ref clientPoint);
                if (nBytes == -1)
                {
                    Console.WriteLine("Host not Responding") ;
                    break;
                }
                else if(nBytes>0)
                {
                    timeConsume = System.Environment.TickCount - startTime;
                    Console.WriteLine("Reply from "+hostPoint.ToString()+" in "
                    +timeConsume+"MS :Bytes Received"+nBytes);
                    break;
                }
                timeConsume=Environment.TickCount - startTime;
                if(timeout>1000)
                {
                    Console.WriteLine("Time Out") ;
                    break;
                }
            }                  
            socket.Close();   
        }
}

    public class IcmpPacket
    {
        private Byte  _type;            // 报文类型
        private Byte  _subCode;        // 字代码类型
        private UInt16 _checkSum;       // 报文校验和
        private UInt16 _identifier;      // 识别符
        private UInt16 _sequenceNumber;     // 序列号
        private Byte [] _data;       

        ///***********************************************************
        ///初始化报文
        ///***********************************************************
        public IcmpPacket(Byte type,Byte subCode,UInt16 checkSum,UInt16 identifier,UInt16 sequenceNumber,int dataSize)
        {
            _type=type;
            _subCode=subCode;
            _checkSum=checkSum;
            _identifier=identifier;
            _sequenceNumber=sequenceNumber;
            _data=new Byte[dataSize];
            for (int i = 0; i < dataSize; i++)
            {
                  _data[i] = (byte)'#';
            }
        }
        public UInt16 CheckSum
        {
            get{ return _checkSum;}
            set{ _checkSum=value; }
        }
      
        ///************************************************************
        ///将整个ICMP报文信息和数据转化为Byte数据包  
        ///************************************************************
        public int ConvertToByte(Byte[] buffer)
        {
            Byte [] b_type = new Byte[1]{_type};
            Byte [] b_code = new Byte[1]{_subCode};
            Byte [] b_cksum = BitConverter.GetBytes(_checkSum);
            Byte [] b_id = BitConverter.GetBytes(_identifier);
            Byte [] b_seq = BitConverter.GetBytes(_sequenceNumber);          
            int i=0;
            Array.Copy( b_type, 0, buffer, i, b_type.Length );
            i+= b_type.Length;
          
            Array.Copy( b_code, 0, buffer, i, b_code.Length );
            i+= b_code.Length;

            Array.Copy( b_cksum, 0, buffer,i, b_cksum.Length );
            i += b_cksum.Length;

            Array.Copy( b_id, 0, buffer, i, b_id.Length );
            i+= b_id.Length;

            Array.Copy( b_seq, 0, buffer, i, b_seq.Length );
            i += b_seq.Length;

            Array.Copy(_data, 0, buffer, i, _data.Length );
            i += _data.Length;

            return i;
        }
        public static UInt16 SumOfCheck( UInt16[] buffer )
        {
            int cksum = 0;
            for(int i=0;i<buffer.Length;i++)
            cksum += (int) buffer[i];

            cksum = (cksum >> 16) + (cksum & 0xffff);
            cksum += (cksum >> 16);
            return (UInt16)(~cksum);    
        }
    }
}

你可能感兴趣的:(ping)