我在使用Mono 3.2.8运行的C#.Net 4.5中遇到Ping.Send的延迟问题。我的代码如下所示:
using(var sw = new StreamWriter("/ping.txt"))
{
var ping = new Ping();
PingReply reply;
sw.WriteLine("Pre ping: {0}", DateTime.Now);
// Ping local machine
reply = ping.Send("172.16.1.100", 60);
sw.WriteLine("Post ping: {0}", DateTime.Now);
if (reply != null && reply.Status == IPStatus.Success)
{
sw.WriteLine("Success! RTT: {0}", reply.RoundtripTime);
}
sw.WriteLine("Pre ping: {0}", DateTime.Now);
// Ping Google
reply = ping.Send("216.58.220.110", 60);
sw.WriteLine("Post ping: {0}", DateTime.Now);
if (reply != null && reply.Status == IPStatus.Success)
{
sw.WriteLine("Success! RTT: {0}", reply.RoundtripTime);
}
}
在Linux上以Mono运行上述代码的输出是:
你可以看到" Pre"和"发布"时间戳,有20秒的延迟(这是一致的,它总是20秒)。运行Mono的机器在同一个172.16.1。*网络上,我把Google ping放在那里进行额外的测试。
在我的Windows机器上本地运行相同的代码会产生以下输出(ping没有延迟):
关于这里发生了什么的任何想法?我需要ping数百台机器,所以ping之间的延迟是20秒是不可接受的。
更新:
我已尝试将Ping.SendAsync
方法与以下代码一起使用:
private void PingAsyncTest()
{
var ipAddresses = new List<String> { "172.16.1.100", "216.58.220.110" };
foreach (var ipAddress in ipAddresses)
{
using (var ping = new Ping())
{
ping.PingCompleted += PingCompleted;
ping.SendAsync(IPAddress.Parse(ipAddress), 1000);
}
}
}
private void PingCompleted(object sender, PingCompletedEventArgs e)
{
if (e.Reply.Status == IPStatus.Success)
{
// Update successful ping in the DB.
}
}
我仍然看到SendAsync
来电和回复PingCompleted
之间的延迟时间为20秒。这比应用程序在发送下一次ping之前等待20秒的原始代码稍微好一点。这样所有ping都是异步发送和接收的,因此每次ping都不需要等待20秒。但仍然不理想。
答案 0 :(得分:1)
这种方式取决于权限的设置方式。
如果您的应用程序获得足够的权限,它将直接尝试发送ICMP请求。另一方面,如果不允许发送ICMP,它将运行ping
可执行文件(尝试在/bin/ping
,/sbin/ping
和/usr/sbin/ping
中找到它。
您可能想要检查的第一件事是实际发生的事情。在您尝试执行ping操作时ping
是否会执行?如果您sudo
申请,会有帮助吗?
默认超时是4秒,因此它不应该永远需要20秒 - 你应该在此之前很久就有一个超时。并且您明确地传递了60毫秒的超时。
所有这些(以及对Mono中代码处理ping的好看)表明其中一个:
Ping
类本身的初始设置需要20秒 - 查询功能,查找ping
等。显然情况并非如此,因为您正在尝试两次ping,每次他们花了很长时间。Dns.GetHostName
或Dns.GetHostAddresses
。单独检查ping本身。最后一点也暗指另一个问题 - 如果你试图ping许多不同的主机,你真的不想使用Ping
,至少在Linux上不行。相反,您需要确保您的应用程序运行特权(足够的权限来执行原始ICMP),并通过单个Socket
处理所有ICMP请求和回复。如果您使用Ping.Send
并行发送100个请求,则每个Ping.Send
都必须通过所有回复,而不仅仅是他们期望的回复。此外,使用60ms作为超时听起来不是一个好主意,因为代码使用DateTime.Now
来检查超时,这可能具有非常低的超时分辨率。
除了发送请求并等待回复之外,您真的希望使用异步套接字来一直发送和接收,直到您通过所有要ping的主机,同时检查您所做的那些主机。及时得到回复。