C#下实现ping操作

1、利用原始Socket套接字,实现ICMP协议。
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Text; 
  4. using System.Net; 
  5. using System.Net.Sockets; 


  6. namespace PingC 

  7.     class ping 
  8.     { 
  9.         const int SOCKET_ERROR = -1; 
  10.         const int ICMP_ECHO = 8; 
  11.         static void Main(string[] args) 
  12.         { 
  13.             ping p = new ping(); 
  14.             Console.WriteLine("请输入要 Ping 的IP或者主机名字:"); 
  15.             string MyUrl = Console.ReadLine(); 
  16.             Console.WriteLine("正在 Ping " + MyUrl + " ……"); 
  17.             Console.Write(p.PingHost(MyUrl)); 
  18.         } 
  19.         public string PingHost(string host) 
  20.         { 
  21.             // 声明 IPHostEntry 
  22.             IPHostEntry ServerHE, fromHE; 
  23.             int nBytes = 0; 
  24.             int dwStart = 0, dwStop = 0; 

  25.             //初始化ICMP的Socket 
  26.             Socket socket = 
  27.             new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp); 
  28.             socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000); 
  29.             // 得到Server EndPoint 
  30.             try 
  31.             { 
  32.                 ServerHE = Dns.GetHostByName(host); 
  33.             } 
  34.             catch (Exception) 
  35.             { 

  36.                 return "没有发现主机"; 
  37.             } 

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

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

  45.             int PacketSize = 0; 
  46.             IcmpPacket packet = new IcmpPacket(); 

  47.             // 构建要发送的包 
  48.             packet.Type = ICMP_ECHO; //8 
  49.             packet.SubCode = 0; 
  50.             packet.CheckSum =0; 
  51.             packet.Identifier = 45; 
  52.             packet.SequenceNumber = 0; 
  53.             int PingData = 24; // sizeof(IcmpPacket) - 8; 
  54.             packet.Data = new Byte[PingData]; 

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

  60.             //Variable to hold the total Packet size 
  61.             PacketSize = 32; 
  62.             Byte[] icmp_pkt_buffer = new Byte[PacketSize]; 
  63.             Int32 Index = 0; 
  64.             //again check the packet size 
  65.             Index = Serialize( 
  66.             packet, 
  67.             icmp_pkt_buffer, 
  68.             PacketSize, 
  69.             PingData); 
  70.             //if there is a error report it 
  71.             if (Index == -1) 
  72.             { 
  73.                 return "Error Creating Packet"; 

  74.             } 
  75.             // convert into a UInt16 array 

  76.             //Get the Half size of the Packet 
  77.             Double double_length = Convert.ToDouble(Index); 
  78.             Double dtemp = Math.Ceiling(double_length / 2); 
  79.             int cksum_buffer_length = Index/2; 
  80.             //Create a Byte Array 
  81.             UInt16[] cksum_buffer = new UInt16[cksum_buffer_length]; 
  82.             //Code to initialize the Uint16 array 
  83.             int icmp_header_buffer_index = 0; 
  84.             for (int i = 0; i < cksum_buffer_length; i++) 
  85.             { 
  86.                 cksum_buffer = 
  87.                 BitConverter.ToUInt16(icmp_pkt_buffer, icmp_header_buffer_index); 
  88.                 icmp_header_buffer_index += 2; 
  89.             } 
  90.             //Call a method which will return a checksum 
  91.             UInt16 u_cksum = checksum(cksum_buffer, cksum_buffer_length); 
  92.             //Save the checksum to the Packet 
  93.             packet.CheckSum = u_cksum; 

  94.             // Now that we have the checksum, serialize the packet again 
  95.             Byte[] sendbuf = new Byte[PacketSize]; 
  96.             //again check the packet size 
  97.             Index = Serialize( 
  98.             packet, 
  99.             sendbuf, 
  100.             PacketSize, 
  101.             PingData); 
  102.             //if there is a error report it 
  103.             if (Index == -1) 
  104.             { 
  105.                 return "Error Creating Packet"; 

  106.             } 

  107.             dwStart = System.Environment.TickCount; // Start timing 
  108.             //send the Packet over the socket 
  109.             if ((nBytes = socket.SendTo(sendbuf, PacketSize, 0, epServer)) == SOCKET_ERROR) 
  110.             { 
  111.                 return "Socket Error: cannot send Packet"; 
  112.             } 
  113.             // Initialize the buffers. The receive buffer is the size of the 
  114.             // ICMP header plus the IP header (20 bytes) 
  115.             Byte[] ReceiveBuffer = new Byte[256]; 
  116.             nBytes = 0; 
  117.             //Receive the bytes 
  118.             bool recd = false; 
  119.             int timeout = 0; 

  120.             //loop for checking the time of the server responding 
  121.             while (!recd) 
  122.             { 
  123.                 nBytes = socket.ReceiveFrom(ReceiveBuffer, 256, 0, ref EndPointFrom); 
  124.                 if (nBytes == SOCKET_ERROR) 
  125.                 { 
  126.                     return "主机没有响应"; 

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

  133.                 } 
  134.                 timeout = System.Environment.TickCount - dwStart; 
  135.                 if (timeout > 1000) 
  136.                 { 
  137.                     return "超时"; 
  138.                 } 
  139.             } 

  140.             //close the socket 
  141.             socket.Close(); 
  142.             return ""; 
  143.         } 
  144.         /// <summary> 
  145.         ///  This method get the Packet and calculates the total size 
  146.         ///  of the Pack by converting it to byte array 
  147.         /// </summary> 
  148.         public static Int32 Serialize(IcmpPacket packet, Byte[] Buffer, 
  149.         Int32 PacketSize, Int32 PingData) 
  150.         { 
  151.             Int32 cbReturn = 0; 
  152.             // serialize the struct into the array 
  153.             int Index = 0; 

  154.             Byte[] b_type = new Byte[1]; 
  155.             b_type[0] = (packet.Type); 

  156.             Byte[] b_code = new Byte[1]; 
  157.             b_code[0] = (packet.SubCode); 

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

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

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

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

  167.             Array.Copy(b_id, 0, Buffer, Index, b_id.Length); 
  168.             Index += b_id.Length; 

  169.             Array.Copy(b_seq, 0, Buffer, Index, b_seq.Length); 
  170.             Index += b_seq.Length; 

  171.             // copy the data 
  172.             Array.Copy(packet.Data, 0, Buffer, Index, PingData); 
  173.             Index += PingData; 
  174.             if (Index != PacketSize/* sizeof(IcmpPacket)  */) 
  175.             { 
  176.                 cbReturn = -1; 
  177.                 return cbReturn; 
  178.             } 

  179.             cbReturn = Index; 
  180.             return cbReturn; 
  181.         } 
  182.         /// <summary> 
  183.         ///  This Method has the algorithm to make a checksum 
  184.         /// </summary> 
  185.         public static UInt16 checksum(UInt16[] buffer, int size) 
  186.         { 
  187.             Int32 cksum = 0; 
  188.             int counter; 
  189.             counter = 0; 

  190.             while (size > 0) 
  191.             { 
  192.                 UInt16 val = buffer[counter]; 

  193.                 cksum += buffer[counter]; 
  194.                 counter += 1; 
  195.                 size -= 1; 
  196.             } 

  197.             cksum = (cksum >> 16) + (cksum & 0xffff); 
  198.             cksum += (cksum >> 16); 
  199.             return (UInt16)(~cksum); 
  200.         } 
  201.     } 
  202.     /// 类结束 
  203.     /// <summary> 
  204.     ///  Class that holds the Pack information 
  205.     /// </summary> 
  206.     public class IcmpPacket 
  207.     { 
  208.         public Byte Type;    // type of message 
  209.         public Byte SubCode;    // type of sub code 
  210.         public UInt16 CheckSum;  // ones complement checksum of struct 
  211.         public UInt16 Identifier;      // identifier 
  212.         public UInt16 SequenceNumber;    // sequence number 
  213.         public Byte[] Data; 

  214.     } // class IcmpPacket 

  215. }
复制代码
2、执行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(); 

3、利用C#2.0新增的Ping类 

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

在button1_click事件键入
  1. private void button1_Click(object sender, EventArgs e) 

  2.     Ping p1 = new Ping(); //只是演示,没有做错误处理 
  3.     PingReply reply = p1.Send(this.textBox1.Text);//阻塞方式 
  4.     displayReply(reply); //显示结果 



  5. private void displayReply(PingReply reply) //显示结果 

  6.     StringBuilder sbuilder ; 
  7.     if (reply.Status == IPStatus.Success) 
  8.     { 
  9.         sbuilder = new StringBuilder(); 
  10.         sbuilder.Append(string.Format("Address: {0} ", reply.Address.ToString ())); 
  11.         sbuilder.Append(string.Format("RoundTrip time: {0} ", reply.RoundtripTime)); 
  12.         sbuilder.Append(string.Format("Time to live: {0} ", reply.Options.Ttl)); 
  13.         sbuilder.Append(string.Format("Don't fragment: {0} ", reply.Options.DontFragment)); 
  14.         sbuilder.Append(string.Format("Buffer size: {0} ", reply.Buffer.Length)); 
  15.         listBox1.Items.Add(sbuilder.ToString()); 
  16.     } 

  17. }
复制代码
也可以做 异步的处理,修改button1_click,并添加PingCompletedCallBack方法
  1. private void button1_Click(object sender, EventArgs e) 

  2.     Ping p1 = new Ping(); 
  3.     p1.PingCompleted += new PingCompletedEventHandler(this.PingCompletedCallBack);//设置PingCompleted事件处理程序 
  4.     p1.SendAsync(this.textBox1.Text, null); 
  5. }

  6. private void PingCompletedCallBack(object sender, PingCompletedEventArgs e) 

  7.     if (e.Cancelled) 
  8.     { 
  9.         listBox1.Items.Add("Ping Canncel"); 
  10.         return; 
  11.     } 
  12.     if (e.Error != null) 
  13.     { 
  14.         listBox1.Items.Add(e.Error.Message); 
  15.         return; 

  16.     } 
  17.     StringBuilder sbuilder; 
  18.     PingReply reply = e.Reply; 
  19.     if (reply.Status == IPStatus.Success) 
  20.     { 
  21.         sbuilder = new StringBuilder(); 
  22.         sbuilder.Append(string.Format("Address: {0} ", reply.Address.ToString())); 
  23.         sbuilder.Append(string.Format("RoundTrip time: {0} ", reply.RoundtripTime)); 
  24.         sbuilder.Append(string.Format("Time to live: {0} ", reply.Options.Ttl)); 
  25.         sbuilder.Append(string.Format("Don't fragment: {0} ", reply.Options.DontFragment)); 
  26.         sbuilder.Append(string.Format("Buffer size: {0} ", reply.Buffer.Length)); 
  27.         listBox1.Items.Add(sbuilder.ToString()); 

  28.     } 
  29. }
复制代码
怎么样,相比1、2方式,3是不是简单的多呀。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值