在C#中获得更快的Ping结果

时间:2013-01-16 15:00:53

标签: c# winforms ping

我正在使用.NET中的“PingReply”类来测试与某个主机的连接。我的问题是如果ping结果失败,需要一段时间才能得到结果。它是LAN环境,所以我已经可以假设连接失败,如果它需要超过100毫秒。如果与主机的连接失败,下面的代码显示5秒后的结果,即5000ms。即使连接失败,我能获得更快的结果吗?

Ping x = new Ping();
PingReply reply = x.Send(IPAddress.Parse("192.168.0.1")); 
if (reply.Status == IPStatus.Success)
{
    //Do something
}

5 个答案:

答案 0 :(得分:3)

由于我们无法看到您的ping对象,因此我假设您不了解TIMEOUT。我通常发送异步ping,并将超时设置为3秒。

 try
            {
                Ping ping = new Ping();
                ping.PingCompleted += (sender, e) =>
                {
                    if (e.Reply.Status != IPStatus.Success)
                        // Report fail
                    else                    
                       // Report success

                };
                ping.SendAsync(target, 3000, target); // Timeout is 3 seconds here
            }
            catch (Exception)
            {
                return;
            }

答案 1 :(得分:3)

您可以将超时传递给Ping.Send()方法。请查看重载的成员。

答案 2 :(得分:3)

Ping.Send()有一个带有超时参数的重载:

PingReply reply = x.Send(IPAddress.Parse("192.168.0.1"), 100);

答案 3 :(得分:2)

您可以使用异步委托来启动Ping。异步委托有一个名为BeginInvoke的函数,它将启动一个后台线程,该线程将立即返回IAsyncResult。 IAsyncResult有一个名为AsyncWaitHandle的等待处理程序,它有一个名为WaitOne的方法,可以为其分配一个等待时间。这将以毫秒为单位冻结当前线程(以毫秒为单位),在您的情况下为100,然后您可以使用属性IsCompleted来检查线程是否已完成其工作。例如:

Func<PingReply>  pingDelegate = () => new Ping().Send(IPAddress.Parse("192.168.0.1"));

IAsyncResult result = pingDelegate.BeginInvoke(r => pingDelegate.EndInvoke(r), null);

//wait for thread to complete
result.AsyncWaitHandle.WaitOne(100);

if (result.IsCompleted)
{
    //Ping Succeeded do something
    PingReply reply = (PingReply) result;

    //Do something with successful reply
}

答案 4 :(得分:1)

我也创建了一个实时主机扫描程序。它使用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文档。