C# ping命令的實(shí)現(xiàn)方法:Ping類的使用
以下介紹C# ping命令的兩種實(shí)現(xiàn)方法。
C# ping命令實(shí)現(xiàn):利用原始Socket套接字,實(shí)現(xiàn)ICMP協(xié)議。
- 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("請(qǐng)輸入要 Ping 的IP或者主機(jī)名字:");
- 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 "沒(méi)有發(fā)現(xiàn)主機(jī)";
- }
- // 把 Server IP_EndPoint轉(zhuǎn)換成EndPoint
- IPEndPoint ipepServer = new IPEndPoint(ServerHE.AddressList[0], 0);
- EndPoint epServer = (ipepServer);
- // 設(shè)定客戶機(jī)的接收Endpoint
- fromHE = Dns.GetHostByName(Dns.GetHostName());
- IPEndPoint ipEndPointFrom = new IPEndPoint(fromHE.AddressList[0], 0);
- EndPoint EndPointFrom = (ipEndPointFrom);
- int PacketSize = 0;
- IcmpPacket packet = new IcmpPacket();
- // 構(gòu)建要發(fā)送的包
- 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 "主機(jī)沒(méi)有響應(yīng)";
- }
- 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 "超時(shí)";
- }
- }
- //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);
- }
- }
- /// 類結(jié)束
- /// < 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命令執(zhí)行:執(zhí)行ping命令
首先,我們用使用Process類,來(lái)創(chuàng)建獨(dú)立的進(jìn)程,導(dǎo)入System.Diagnostics,
using System.Diagnostics;
實(shí)例一個(gè)Process類,啟動(dòng)一個(gè)獨(dú)立進(jìn)程
Process p = new Process();
Process類有一個(gè)StartInfo屬性,這個(gè)是ProcessStartInfo類,包括了一些屬性和方法,
下面我們用到了他的幾個(gè)屬性:
設(shè)定程序名
p.StartInfo.FileName = "cmd.exe";
關(guān)閉Shell的使用
p.StartInfo.UseShellExecute = false;
重定向標(biāo)準(zhǔn)輸入
p.StartInfo.RedirectStandardInput = true;
重定向標(biāo)準(zhǔn)輸出
p.StartInfo.RedirectStandardOutput = true;
重定向錯(cuò)誤輸出
p.StartInfo.RedirectStandardError = true;
設(shè)置不顯示窗口
p.StartInfo.CreateNoWindow = true;
上面幾個(gè)屬性的設(shè)置是比較關(guān)鍵的一步。
既然都設(shè)置好了那就啟動(dòng)進(jìn)程吧,
p.Start();
輸入要執(zhí)行的命令,這里就是ping了,