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

本文关键字:何更快 ping IP 访问 | 更新日期: 2023-09-27 18:20:40

我有一个应用程序,它会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);
    }

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

您不应该减少超时时间。尝试同时异步发送多个ping。

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

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

我建议您使用过载来代替IPAddress

不久前我创建了一个实时主机扫描仪。它使用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也会使用此技术来扫描可用的主机。

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

编辑:

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

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

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

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

不确定这是否有任何帮助(请参阅线程的最后一篇文章),这似乎是一个几乎相同的问题。你碰到的是协议栈的超时。如果你使用插座连接,你可以绕过它,因为你会有更多的控制权。