当我到达无法访问的IP时如何更快地ping通?

时间:2012-01-19 10:05:37

标签: c# winforms ping

我有一个ping IP或IP范围的应用程序。问题是当主机关闭时,ping它比打开它需要更长的时间。当主机关闭时,ping的时间大约是1-2秒。

如果主机关闭,我怎么能让它更快?

这是我的代码:

using System;
using System.Text;
using System.Windows.Forms;
using System.Net.NetworkInformation;

namespace Range_Pinger
{
    public partial class PingIPRange : Form
    {
        uint startIP, endIP, currentIP;
        int count = 0;
        int open = 0;
        int closed = 0;

        public PingIPRange()
        {
            InitializeComponent();

            tmrPingInterval.Tick += new EventHandler(tmrPingInterval_Tick);
        }

        void tmrPingInterval_Tick(object sender, EventArgs e)
        {
            if (txtTo.Text == string.Empty) Ping(ip2str(startIP));
            else
            {
                if (currentIP >= endIP) tmrPingInterval.Stop();
                Ping(ip2str(currentIP));
                currentIP++;
            }

            count++;

            tsslPingCount.Text = "Total number of pings: " + count.ToString() + 
                " Open IPs: " + open.ToString() + " Closed IPs: " + closed.ToString();
        }

        static uint str2ip(string ip)
        {
            string[] numbers = ip.Split('.');

            uint x1 = (uint)(Convert.ToByte(numbers[0]) << 24);
            uint x2 = (uint)(Convert.ToByte(numbers[1]) << 16);
            uint x3 = (uint)(Convert.ToByte(numbers[2]) << 8);
            uint x4 = (uint)(Convert.ToByte(numbers[3]));

            return x1 + x2 + x3 + x4;
        }

        static string ip2str(uint ip)
        {
            string s1 = ((ip & 0xff000000) >> 24).ToString() + ".";
            string s2 = ((ip & 0x00ff0000) >> 16).ToString() + ".";
            string s3 = ((ip & 0x0000ff00) >> 8).ToString() + ".";
            string s4 = (ip & 0x000000ff).ToString();

            return s1 + s2 + s3 + s4;
        }


        private void btnPing_Click(object sender, EventArgs e)
        {
            txtDisplay.Text = string.Empty;
            tsslPingCount.Text = string.Empty; 
            count = 0;
            open = 0;
            closed = 0;
            tmrPingInterval.Interval = int.Parse(nudInterval.Value.ToString());

            try
            {
                startIP = str2ip(txtFrom.Text);
                if (txtTo.Text != string.Empty) endIP = str2ip(txtTo.Text);
                currentIP = startIP;
                tmrPingInterval.Start();
            }
            catch
            {
                MessageBox.Show("Invalid input. It must be something like: 255.255.255.255");
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            tmrPingInterval.Stop();
        }

        private void Ping(string address)
        {
            Ping pingSender = new Ping();
            PingOptions options = new PingOptions();
            options.DontFragment = true;
            string data = "01234567890123456789012345678901";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            int timeout = 120;
            try
            {
                PingReply reply = pingSender.Send(address, timeout, buffer, options) ;
                if (reply.Status == IPStatus.Success)
                {
                    open++;
                    txtDisplay.AppendText("Host " + address + " is open." + Environment.NewLine);
                }
                else
                {
                    closed++;
                    txtDisplay.AppendText("Host " + address + " is closed." + Environment.NewLine);
                }
            }
            catch (Exception ex)
            {
                txtDisplay.SelectedText += Environment.NewLine + ex.Message;
            }
        }

        private void tsmiExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

这就是我现在所拥有的:

    [DllImport("iphlpapi.dll", ExactSpelling = true)]
    public static extern int SendARP(IPAddress DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);

    private void Ping(IPAddress address)
    {
        byte[] macAddr = new byte[6];
        uint macAddrLen = (uint)macAddr.Length;

        if (SendARP(address, 0, macAddr, ref macAddrLen) == 0)
        {
            txtDisplay.AppendText("Host " + address + " is open." + Environment.NewLine);
        }
        else txtDisplay.AppendText("Host " + address + " is closed." + Environment.NewLine);
    }

5 个答案:

答案 0 :(得分:10)

你不应该减少超时。尝试一次发送多个ping异步。

var ping = new Ping();
ping.PingCompleted += (sender, eventArgs) =>
{
    // eventArgs.Reply.Address
    // eventArgs.Reply.Status
};
ping.SendAsync(ip, etc.);

答案 1 :(得分:7)

您的地址是string。因此,它将首先通过DNS查看这是否可能是主机名(即使它是一个IP地址)。

我建议您使用重载IPAddress代替。

答案 2 :(得分:4)

我不久前创建了一个实时主机扫描程序。它使用ARP来检查计算机是否在线。 ARP请求比ping主机要快得多。 这是我用来检查主机是否可用的代码:

//You'll need this pinvoke signature as it is not part of the .Net framework
[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(int DestIP, int SrcIP, 
                                 byte[] pMacAddr, ref uint PhyAddrLen);

//These vars are needed, if the the request was a success 
//the MAC address of the host is returned in macAddr
private byte[] macAddr = new byte[6];
private uint macAddrLen;

//Here you can put the IP that should be checked
private IPAddress Destination = IPAddress.Parse("127.0.0.1");

//Send Request and check if the host is there
if (SendARP((int)Destination.Address, 0, macAddr, ref macAddrLen) == 0)
{
    //SUCCESS! Igor it's alive!
}

如果您对Nmap also uses this technique感兴趣,可以扫描可用的主机。

  

ARP扫描使Nmap及其优化算法负责ARP请求。如果它得到回复,Nmap甚至不需要担心基于IP的ping数据包,因为它已经知道主机已启动。这使得ARP扫描比基于IP的扫描更快,更可靠。因此,在扫描Nmap检测到的以太网主机上的以太网主机时,默认情况下会完成此操作。即使指定了不同的ping类型(例如-PE或-PS),Nmap也会使用ARP代替同一LAN上的任何目标。

编辑:

这仅适用于当前子网!只要请求机器和目标之间没有路由器就可以正常工作。

  

ARP是一种不可路由的协议,因此只能在同一以太网上的系统之间使用。 [...]   arp-scan可用于发现本地网络上的IP主机。它可以发现所有主机,包括阻止所有IP流量的主机,例如防火墙和具有入口过滤器的系统。 - Excerpt from NTA-Monitor wiki

有关SendARP功能的更多信息,您可以查看pinvoke.net文档。

答案 3 :(得分:3)

您需要重新设计应用程序以使用多线程 - &gt;任务。为每个ping发出一个任务,当您收到来自给定主机的响应时,触发一个事件并更新UI。更改套接字超时只会帮助您减少从令人发指的到令人难以忍受的超时。

答案 4 :(得分:2)

不确定this is any help(见线程上的最后帖子),这似乎是一个几乎相同的问题。你正在对抗的是协议栈的超时。如果您使用套接字连接,可以绕过它,因为您可以获得更多控制权。