1

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

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

5 回答 5

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;
            }
于 2013-01-16T15:04:36.110 回答
3

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

于 2013-01-16T15:05:58.753 回答
3

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

PingReply reply = x.Send(IPAddress.Parse("192.168.0.1"), 100);
于 2013-01-16T15:07:27.447 回答
3

您可以使用异步委托来启动 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
}
于 2013-01-16T15:35:40.333 回答
2

我也创建了一个实时主机扫描仪。它使用 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-scan 可用于发现本地网络上的 IP 主机。它可以发现所有主机,包括那些阻止所有 IP 流量的主机,例如防火墙和带有入口过滤器的系统。-摘自 NTA-Monitor 维基

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

于 2020-08-21T13:02:57.780 回答