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

开发 后端
本文介绍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操作》。

【编辑推荐】

  1. 利用C#正则表达式提取相关URL中的域名
  2. 介绍Mono C#编译器
  3. C#运算符重载学习总结
  4. 概述C#语言的结构体
  5. C#遗传算法学习笔记
责任编辑:yangsai 来源: 网络小筑的博客
相关推荐

2009-08-17 10:54:53

C#执行ping命令

2010-10-08 14:16:29

2010-08-02 16:11:29

ICMP协议

2010-07-30 16:10:57

ICMPping

2017-03-03 11:40:59

linuxping命令

2010-08-02 14:29:46

LinuxPingICMP

2017-02-07 18:34:16

Linux编程PING

2011-09-09 09:29:37

192.168.1.1pingping 192.16

2023-11-01 11:27:42

ping命令网络

2010-01-06 18:33:56

.Net Framew

2022-11-20 16:21:33

Linuxping 命令网络连接

2014-12-23 09:47:34

2011-08-10 11:02:14

2013-11-27 10:36:47

命令行工具ping工具

2020-05-09 16:45:56

ping命令Linux

2009-08-20 18:21:04

GetType方法C# object类

2019-05-13 10:03:31

Ping命令故障网络

2010-12-31 13:44:33

pingnet view

2019-04-15 10:26:26

Linux服务器内核

2009-09-07 09:36:29

C# DisposeDispose方法
点赞
收藏

51CTO技术栈公众号