C# ping命令的实现方法:Ping类的使用

来源:互联网 发布:网络法律法规对游戏 编辑:程序博客网 时间:2024/06/06 16:32
    本文介绍C# ping命令的实现方法,首先利用原始Socket套接字,实现ICMP协议,然后执行ping命令。最后,还可以使用C# 2.0中新增的Ping类来实现。

     

    以下介绍C# ping命令的两种实现方法。

    C# ping命令实现:利用原始Socket套接字,实现ICMP协议。

    1. using System;   
    2. using System.Collections.Generic;   
    3. using System.Text;   
    4. using System.Net;   
    5. using System.Net.Sockets;   
    6.  
    7.  
    8. namespace PingC   
    9. {   
    10.     class ping   
    11.     {   
    12.         const int SOCKET_ERROR = -1;   
    13.         const int ICMP_ECHO = 8;   
    14.         static void Main(string[] args)   
    15.         {   
    16.             ping p = new ping();   
    17.             Console.WriteLine("请输入要 Ping 的IP或者主机名字:");   
    18.             string MyUrl = Console.ReadLine();   
    19.             Console.WriteLine("正在 Ping " + MyUrl + " ……");   
    20.             Console.Write(p.PingHost(MyUrl));   
    21.         }   
    22.         public string PingHost(string host)   
    23.         {   
    24.             // 声明 IPHostEntry   
    25.             IPHostEntry ServerHE, fromHE;   
    26.             int nBytes = 0;   
    27.             int dwStart = 0, dwStop = 0;   
    28.  
    29.             //初始化ICMP的Socket   
    30.             Socket socket =   
    31.              new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);   
    32.             socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000);   
    33.             // 得到Server EndPoint   
    34.             try   
    35.             {   
    36.                 ServerHE = Dns.GetHostByName(host);   
    37.             }   
    38.             catch (Exception)   
    39.             {   
    40.  
    41.                 return "没有发现主机";   
    42.             }   
    43.  
    44.             // 把 Server IP_EndPoint转换成EndPoint   
    45.             IPEndPoint ipepServer = new IPEndPoint(ServerHE.AddressList[0], 0);   
    46.             EndPoint epServer = (ipepServer);   
    47.  
    48.             // 设定客户机的接收Endpoint   
    49.             fromHE = Dns.GetHostByName(Dns.GetHostName());   
    50.             IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0], 0);   
    51.             EndPoint EndPointFrom = (ipEndPointFrom);   
    52.  
    53.             int PacketSize = 0;   
    54.             IcmpPacket packet = new IcmpPacket();   
    55.  
    56.             // 构建要发送的包   
    57.             packet.Type = ICMP_ECHO; //8   
    58.             packet.SubCode = 0;   
    59.             packet.CheckSum =0;   
    60.             packet.Identifier = 45;   
    61.             packet.SequenceNumber = 0;   
    62.             int PingData = 24; // sizeof(IcmpPacket) - 8;   
    63.             packet.Data = new Byte[PingData];   
    64.  
    65.             // 初始化Packet.Data   
    66.             for (int i = 0; i <  PingData; i++)   
    67.             {   
    68.                 packet.Data[i] = (byte)'#';   
    69.             }   
    70.  
    71.             //Variable to hold the total Packet size   
    72.             PacketSize = 32;   
    73.             Byte[] icmp_pkt_buffer = new Byte[PacketSize];   
    74.             Int32 Index = 0;   
    75.             //again check the packet size   
    76.             Index = Serialize(   
    77.              packet,   
    78.              icmp_pkt_buffer,   
    79.              PacketSize,   
    80.              PingData);   
    81.             //if there is a error report it   
    82.             if (Index == -1)   
    83.             {   
    84.                 return "Error Creating Packet";   
    85.  
    86.             }   
    87.             // convert into a UInt16 array   
    88.  
    89.             //Get the Half size of the Packet   
    90.             Double double_length = Convert.ToDouble(Index);   
    91.             Double dtemp = Math.Ceiling(double_length / 2);   
    92.             int cksum_buffer_length = Index/2;   
    93.             //Create a Byte Array   
    94.             UInt16[] cksum_buffer = new UInt16[cksum_buffer_length];   
    95.             //Code to initialize the Uint16 array   
    96.             int icmp_header_buffer_index = 0;   
    97.             for (int i = 0; i <  cksum_buffer_length; i++)   
    98.             {   
    99.                 cksum_buffer[i] =   
    100.                  BitConverter.ToUInt16(icmp_pkt_buffer, icmp_header_buffer_index);   
    101.                 icmp_header_buffer_index += 2;   
    102.             }   
    103.             //Call a method which will return a checksum   
    104.             UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length);   
    105.             //Save the checksum to the Packet   
    106.             packet.CheckSum = u_cksum;   
    107.  
    108.             // Now that we have the checksum, serialize the packet again   
    109.             Byte[] sendbuf = new Byte[PacketSize];   
    110.             //again check the packet size   
    111.             Index = Serialize(   
    112.              packet,   
    113.              sendbuf,   
    114.              PacketSize,   
    115.              PingData);   
    116.             //if there is a error report it   
    117.             if (Index == -1)   
    118.             {   
    119.                 return "Error Creating Packet";   
    120.  
    121.             }   
    122.  
    123.             dwStart = System.Environment.TickCount; // Start timing   
    124.             //send the Packet over the socket   
    125.             if ((nBytes = socket.SendTo(sendbuf, PacketSize, 0, epServer)) == SOCKET_ERROR)   
    126.             {   
    127.                 return "Socket Error: cannot send Packet";   
    128.             }   
    129.             // Initialize the buffers. The receive buffer is the size of the   
    130.             // ICMP header plus the IP header (20 bytes)   
    131.             Byte[] ReceiveBuffer = new Byte[256];   
    132.             nBytes = 0;   
    133.             //Receive the bytes   
    134.             bool recd = false;   
    135.             int timeout = 0;   
    136.  
    137.             //loop for checking the time of the server responding   
    138.             while (!recd)   
    139.             {   
    140.                 nBytes = socket.ReceiveFrom(ReceiveBuffer, 256, 0, ref EndPointFrom);   
    141.                 if (nBytes == SOCKET_ERROR)   
    142.                 {   
    143.                     return "主机没有响应";   
    144.  
    145.                 }   
    146.                 else if (nBytes > 0)   
    147.                 {   
    148.                     dwStop = System.Environment.TickCount - dwStart; // stop timing   
    149.                     return "Reply from " + epServer.ToString() + " in "   
    150.                     + dwStop + "ms.  Received: " + nBytes + " Bytes.";   
    151.  
    152.                 }   
    153.                 timeout = System.Environment.TickCount - dwStart;   
    154.                 if (timeout > 1000)   
    155.                 {   
    156.                     return "超时";   
    157.                 }   
    158.             }   
    159.  
    160.             //close the socket   
    161.             socket.Close();   
    162.             return "";   
    163.         }   
    164.         /// < summary>   
    165.         ///  This method get the Packet and calculates the total size   
    166.         ///  of the Pack by converting it to byte array   
    167.         /// < /summary>   
    168.         public static Int32 Serialize(IcmpPacket packet, Byte[] Buffer,   
    169.          Int32 PacketSize, Int32 PingData)   
    170.         {   
    171.             Int32 cbReturn = 0;   
    172.             // serialize the struct into the array   
    173.             int Index = 0;   
    174.  
    175.             Byte[] b_type = new Byte[1];   
    176.             b_type[0] = (packet.Type);   
    177.  
    178.             Byte[] b_code = new Byte[1];   
    179.             b_code[0] = (packet.SubCode);   
    180.  
    181.             Byte[] b_cksum = BitConverter.GetBytes(packet.CheckSum);   
    182.             Byte[] b_id = BitConverter.GetBytes(packet.Identifier);   
    183.             Byte[] b_seq = BitConverter.GetBytes(packet.SequenceNumber);   
    184.  
    185.             Array.Copy(b_type, 0, Buffer, Index, b_type.Length);   
    186.             Index += b_type.Length;   
    187.  
    188.             Array.Copy(b_code, 0, Buffer, Index, b_code.Length);   
    189.             Index += b_code.Length;   
    190.  
    191.             Array.Copy(b_cksum, 0, Buffer, Index, b_cksum.Length);   
    192.             Index += b_cksum.Length;   
    193.  
    194.             Array.Copy(b_id, 0, Buffer, Index, b_id.Length);   
    195.             Index += b_id.Length;   
    196.  
    197.             Array.Copy(b_seq, 0, Buffer, Index, b_seq.Length);   
    198.             Index += b_seq.Length;   
    199.  
    200.             // copy the data   
    201.             Array.Copy(packet.Data, 0, Buffer, Index, PingData);   
    202.             Index += PingData;   
    203.             if (Index != PacketSize/* sizeof(IcmpPacket)  */)   
    204.             {   
    205.                 cbReturn = -1;   
    206.                 return cbReturn;   
    207.             }   
    208.  
    209.             cbReturn = Index;   
    210.             return cbReturn;   
    211.         }   
    212.         /// < summary>   
    213.         ///  This Method has the algorithm to make a checksum   
    214.         /// < /summary>   
    215.         public static UInt16 checksum(UInt16[] buffer, int size)   
    216.         {   
    217.             Int32 cksum = 0;   
    218.             int counter;   
    219.             counter = 0;   
    220.  
    221.             while (size > 0)   
    222.             {   
    223.                 UInt16 val = buffer[counter];   
    224.  
    225.                 cksum += buffer[counter];   
    226.                 counter += 1;   
    227.                 size -= 1;   
    228.             }   
    229.  
    230.             cksum = (cksum >> 16) + (cksum & 0xffff);   
    231.             cksum += (cksum >> 16);   
    232.             return (UInt16)(~cksum);   
    233.         }   
    234.     }   
    235.     /// 类结束   
    236.     /// < summary>   
    237.     ///  Class that holds the Pack information   
    238.     /// < /summary>   
    239.     public class IcmpPacket   
    240.     {   
    241.         public Byte Type;    // type of message   
    242.         public Byte SubCode;    // type of sub code   
    243.         public UInt16 CheckSum;   // ones complement checksum of struct   
    244.         public UInt16 Identifier;      // identifier   
    245.         public UInt16 SequenceNumber;     // sequence number   
    246.         public Byte[] Data;   
    247.  
    248.     } // class IcmpPacket   
    249.  
    250. }   

    C# ping命令执行:执行ping命令

    首先,我们用使用Process类,来创建独立的进程,导入System.Diagnostics,

    using System.Diagnostics;

    实例一个Process类,启动一个独立进程

    Process p = new Process();

    Process类有一个StartInfo属性,这个是ProcessStartInfo类,包括了一些属性和方法,

    下面我们用到了他的几个属性:

    设定程序名

    p.StartInfo.FileName = "cmd.exe";

    关闭Shell的使用

    p.StartInfo.UseShellExecute = false;

    重定向标准输入

    p.StartInfo.RedirectStandardInput = true;

    重定向标准输出

    p.StartInfo.RedirectStandardOutput = true;

    重定向错误输出

    p.StartInfo.RedirectStandardError = true;

    设置不显示窗口

    p.StartInfo.CreateNoWindow = true;

    上面几个属性的设置是比较关键的一步。

    既然都设置好了那就启动进程吧,

    p.Start();

    输入要执行的命令,这里就是ping了,

    p.StandardInput.WriteLine("ping -n 1 www.iwebtrados.com.cn");

    p.StandardInput.WriteLine("exit");

    从输出流获取命令执行结果,

    string strRst = p.StandardOutput.ReadToEnd();

    C# ping命令实现:利用c#2.0新增的Ping类

    这里我写的是一个窗体程序。首先添加textbox,listbox,button控件,其中textbox录入域名或IP,listbox显示结果.

    在button1_click事件键入

    1. private void button1_Click(object sender, EventArgs e)   
    2. {   
    3.     Ping p1 = new Ping(); //只是演示,没有做错误处理   
    4.     PingReply reply = p1.Send(this.textBox1.Text);//阻塞方式   
    5.     displayReply(reply); //显示结果   
    6.  
    7. }   
    8.  
    9. private void displayReply(PingReply reply) //显示结果   
    10. {   
    11.     StringBuilder sbuilder ;   
    12.     if (reply.Status == IPStatus.Success)   
    13.     {   
    14.         sbuilder = new StringBuilder();   
    15.         sbuilder.Append(string.Format("Address: {0} ", reply.Address.ToString ()));   
    16.         sbuilder.Append(string.Format("RoundTrip time: {0} ", reply.RoundtripTime));   
    17.         sbuilder.Append(string.Format("Time to live: {0} ", reply.Options.Ttl));   
    18.         sbuilder.Append(string.Format("Don't fragment: {0} ", reply.Options.DontFragment));   
    19.         sbuilder.Append(string.Format("Buffer size: {0} ", reply.Buffer.Length));   
    20.         listBox1.Items.Add(sbuilder.ToString());   
    21.     }   
    22.  
    23. }  

    也可以做异步的处理,修改button1_click,并添加PingCompletedCallBack方法

    1. private void button1_Click(object sender, EventArgs e)   
    2. {   
    3.     Ping p1 = new Ping();   
    4.     p1.PingCompleted += new PingCompletedEventHandler(this.PingCompletedCallBack);//设置PingCompleted事件处理程序   
    5.     p1.SendAsync(this.textBox1.Text, null);   
    6. }  
    7.  
    8. private void PingCompletedCallBack(object sender, PingCompletedEventArgs e)   
    9. {   
    10.     if (e.Cancelled)   
    11.     {   
    12.         listBox1.Items.Add("Ping Canncel");   
    13.         return;   
    14.     }   
    15.     if (e.Error != null)   
    16.     {   
    17.         listBox1.Items.Add(e.Error.Message);   
    18.         return;   
    19.  
    20.     }   
    21.     StringBuilder sbuilder;   
    22.     PingReply reply = e.Reply;   
    23.     if (reply.Status == IPStatus.Success)   
    24.     {   
    25.         sbuilder = new StringBuilder();   
    26.         sbuilder.Append(string.Format("Address: {0} ", reply.Address.ToString()));   
    27.         sbuilder.Append(string.Format("RoundTrip time: {0} ", reply.RoundtripTime));   
    28.         sbuilder.Append(string.Format("Time to live: {0} ", reply.Options.Ttl));   
    29.         sbuilder.Append(string.Format("Don't fragment: {0} ", reply.Options.DontFragment));   
    30.         sbuilder.Append(string.Format("Buffer size: {0} ", reply.Buffer.Length));   
    31.         listBox1.Items.Add(sbuilder.ToString());   
    32.  
    33.     }   
    34. }  

    怎么样,相比1、2方式,3是不是简单的多呀。

    本文来自网络小筑的博客:《c#下实现ping操作》。

原创粉丝点击