以下介绍C# ping命令的两种实现方法。
C# ping命令实现:利用原始Socket套接字,实现ICMP协议。
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Net;
- using System.Net.Sockets;
- namespace PingC
- {
- class ping
- {
- const int SOCKET_ERROR = -1;
- const int ICMP_ECHO = 8;
- static void Main(string[] args)
- {
- ping p = new ping();
- Console.WriteLine("请输入要 Ping 的IP或者主机名字:");
- string MyUrl = Console.ReadLine();
- Console.WriteLine("正在 Ping " + MyUrl + " ……");
- Console.Write(p.PingHost(MyUrl));
- }
- 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], 0);
- EndPoint epServer = (ipepServer);
- // 设定客户机的接收Endpoint
- fromHE = Dns.GetHostByName(Dns.GetHostName());
- IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0], 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[PingData];
- // 初始化Packet.Data
- for (int i = 0; i < PingData; i++)
- {
- packet.Data[i] = (byte)'#';
- }
- //Variable to hold the total Packet size
- PacketSize = 32;
- Byte[] icmp_pkt_buffer = new Byte[PacketSize];
- 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[cksum_buffer_length];
- //Code to initialize the Uint16 array
- int icmp_header_buffer_index = 0;
- for (int i = 0; i < cksum_buffer_length; i++)
- {
- cksum_buffer[i] =
- 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[PacketSize];
- //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[256];
- 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, 256, 0, ref EndPointFrom);
- if (nBytes == SOCKET_ERROR)
- {
- return "主机没有响应";
- }
- else if (nBytes > 0)
- {
- dwStop = System.Environment.TickCount - dwStart; // stop timing
- return "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[1];
- b_type[0] = (packet.Type);
- Byte[] b_code = new Byte[1];
- b_code[0] = (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[counter];
- cksum += buffer[counter];
- 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;
- } // class IcmpPacket
- }
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事件键入
- private void button1_Click(object sender, EventArgs e)
- {
- Ping p1 = new Ping(); //只是演示,没有做错误处理
- PingReply reply = p1.Send(this.textBox1.Text);//阻塞方式
- displayReply(reply); //显示结果
- }
- private void displayReply(PingReply reply) //显示结果
- {
- StringBuilder sbuilder ;
- if (reply.Status == IPStatus.Success)
- {
- sbuilder = new StringBuilder();
- sbuilder.Append(string.Format("Address: {0} ", reply.Address.ToString ()));
- sbuilder.Append(string.Format("RoundTrip time: {0} ", reply.RoundtripTime));
- sbuilder.Append(string.Format("Time to live: {0} ", reply.Options.Ttl));
- sbuilder.Append(string.Format("Don't fragment: {0} ", reply.Options.DontFragment));
- sbuilder.Append(string.Format("Buffer size: {0} ", reply.Buffer.Length));
- listBox1.Items.Add(sbuilder.ToString());
- }
- }
也可以做异步的处理,修改button1_click,并添加PingCompletedCallBack方法
- private void button1_Click(object sender, EventArgs e)
- {
- Ping p1 = new Ping();
- p1.PingCompleted += new PingCompletedEventHandler(this.PingCompletedCallBack);//设置PingCompleted事件处理程序
- p1.SendAsync(this.textBox1.Text, null);
- }
- private void PingCompletedCallBack(object sender, PingCompletedEventArgs e)
- {
- if (e.Cancelled)
- {
- listBox1.Items.Add("Ping Canncel");
- return;
- }
- if (e.Error != null)
- {
- listBox1.Items.Add(e.Error.Message);
- return;
- }
- StringBuilder sbuilder;
- PingReply reply = e.Reply;
- if (reply.Status == IPStatus.Success)
- {
- sbuilder = new StringBuilder();
- sbuilder.Append(string.Format("Address: {0} ", reply.Address.ToString()));
- sbuilder.Append(string.Format("RoundTrip time: {0} ", reply.RoundtripTime));
- sbuilder.Append(string.Format("Time to live: {0} ", reply.Options.Ttl));
- sbuilder.Append(string.Format("Don't fragment: {0} ", reply.Options.DontFragment));
- sbuilder.Append(string.Format("Buffer size: {0} ", reply.Buffer.Length));
- listBox1.Items.Add(sbuilder.ToString());
- }
- }
怎么样,相比1、2方式,3是不是简单的多呀。
本文来自网络小筑的博客:《c#下实现ping操作》。
【编辑推荐】