zoukankan      html  css  js  c++  java
  • c#下实现ping操作

    1、利用原始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; //
                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, 2560ref 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 



    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事件键入


    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()); 

        } 
    }

  • 相关阅读:
    ROS中.launch文件的remap标签详解
    宝宝刷 leetcode
    ROS rosrun 调用 sudo 命令
    在moveit编译时找不到manipulation_msgsConfig.cmake manipulation_msgs-config.cmake文件
    CMake error with move_base_msgs问题解决
    VIVE pro和hololens购买调研
    /usr/bin/ld: 找不到 -lmsc----解决方案
    ubuntu16.04安装kinetic调用gazebo_control解决方案
    tomcat http协议与ajp协议
    GC日志分析
  • 原文地址:https://www.cnblogs.com/luluping/p/1809819.html
Copyright © 2011-2022 走看看