单声道下的C#Ping延迟/缓慢 [英] C# Ping delay/slow under Mono

查看:276
本文介绍了单声道下的C#Ping延迟/缓慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Mono 3.2.8下运行的C#.Net 4.5中遇到Ping.Send的延迟问题.我的代码如下:

I'm experiencing a delay issue with Ping.Send in C# .Net 4.5 running under Mono 3.2.8. My code looks like this:

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下运行上述代码的输出为:

The output from running the above code under Mono on Linux is:

  1. 预ping:2015年3月17日15:43:21
  2. ping:03/17/2015 15:43:41
  3. 成功! RTT:2
  4. 预ping:2015年3月17日15:43:41
  5. 发帖时间:2015年3月17日15:44:01
  6. 成功! RTT:46

您可以看到在"Pre"和"Post"时间戳之间有20秒的延迟(这是一致的,始终为20秒).运行Mono的计算机位于相同的172.16.1.*网络上,我将Google ping放入该网络中进行了额外的测试.

You can see that between the "Pre" and "Post" timestamps, there is a delay of 20 seconds (this is consistent, it's always 20 seconds). The machine running Mono is on the same 172.16.1.* network, I threw the Google ping in there for an extra test.

在Windows计算机上本地运行相同的代码会产生以下输出(在ping上没有延迟):

Running the same code locally on my Windows machine produces the following output (no delay on the pings):

  1. 预ping:17/03/2015 3:38:21 PM
  2. ping ping:17/03/2015 3:38:21 PM
  3. 成功! RTT:3
  4. 预ping:17/03/2015 3:38:21 PM
  5. ping ping:17/03/2015 3:38:21 PM
  6. 成功! RTT:46

关于这里发生的事情有什么想法吗?我需要对数百台计算机执行ping操作,因此两次ping之间的延迟间隔为20秒是不可接受的.

Any ideas as to what's going on here? I have the need for pinging hundreds of machines, so a delay of 20 seconds between pings isn't acceptable.

更新: 我尝试将Ping.SendAsync方法与下面的代码一起使用:

UPDATE: I've tried using the Ping.SendAsync method with the code below:

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秒的延迟.这比原始代码要好一些,在原始代码中,应用程序将等待20秒再发送下一次ping.这样,所有ping都会异步发送和接收,因此无需为每个ping等待20秒.不过还是不理想.

I'm still seeing the 20 second delay between the SendAsync call and when the reply comes into PingCompleted. This is slightly nicer than the original code where the application would wait the 20 seconds before sending off the next ping. This way all pings are sent and received asynchronously, so there is no need to wait 20 seconds for each ping. Still not ideal though.

推荐答案

这种方式很大程度上取决于权限的设置方式.

The way this goes depends very much on how the permissions are set up.

如果您的应用程序获得足够的权限,它将直接尝试发送ICMP请求.另一方面,如果不允许发送ICMP,它将运行ping可执行文件(尝试在/bin/ping/sbin/ping/usr/sbin/ping中找到它).

If your application gets enough permissions, it will directly try to send an ICMP request. On the other hand, if it's not allowed to send ICMP, it will run ping executable (trying to find it in /bin/ping, /sbin/ping and /usr/sbin/ping).

您可能要检查的第一件事是实际发生的情况.尝试执行ping操作时,ping是否执行?如果您sudo您的应用程序有帮助吗?

First thing you might want to check is which of those actually happens. Does ping execute while you're trying to do the pings? Does it help if you sudo your application?

默认超时为4秒,所以它永远不会花费20秒-您应该早于此超时.并且您明确传递了60毫秒的超时时间.

The default timeout is four seconds, so it shouldn't ever take 20 seconds - you should have gotten a timeout long before that. And you're explicitly passing a timeout of 60 milliseconds.

所有这些(以及对Mono中ping处理代码的全面了解)建议了其中之一:

All this (along with a good look at the code handling pings in Mono) suggests one of those:

  • Ping类本身的初始设置需要20s-查询功能,查找ping等.显然不是这种情况,因为您要尝试两次ping,而每个ping都要这样做长.
  • 大部分时间都花费在实际的ICMP/ping代码之外.最可能的位置是例如Dns.GetHostNameDns.GetHostAddresses.与ping本身分开检查两者.
  • 某些其他线程/进程正在干扰您自己的ping. ICMP套接字将获得 all ICMP响应,因为ICMP中没有端口等概念.
  • The 20s are required for the initial setup of the Ping class itself - querying for capabilities, finding ping etc. This obviously isn't the case, since you're trying two pings and each of them takes this long.
  • Most of the time is spent outside of the actual ICMP/ping code. The most likely place being for example Dns.GetHostName or Dns.GetHostAddresses. Check both separately from the ping itself.
  • Some other thread / process is interfering with your own pings. The ICMP socket will get all the ICMP responses, since there's no concept of ports etc. in ICMP.

最后一点也暗示了另一个问题-如果您要ping通许多不同的主机,则您确实不想使用Ping,至少在Linux上不使用.相反,您将要确保您的应用程序已特权运行(有足够的权限执行原始ICMP),并通过单个Socket处理所有ICMP请求和答复.如果您使用Ping.Send并行发送100个请求,则每个Ping.Send都将必须通过 all 答复,而不仅仅是他们期望的答复.另外,将60ms用作超时听起来不是一个好主意,因为代码使用DateTime.Now来检查超时,这可能具有非常低的超时分辨率.

The last point is also alluding to another issue - if you're trying to ping a lot of different hosts, you really don't want to use Ping, at least not on Linux. Instead, you'll want to ensure your application runs priviledged (enough permissions to do raw ICMP), and handle all the ICMP requests and replies over a single Socket. If you send 100 requests in parallel using Ping.Send, each of those Ping.Sends will have to go through all the replies, not just the one they are expecting. Also, using 60ms as a timeout doesn't sound like a good idea, since the code is using DateTime.Now to check the timeouts, which can have very low timeout resolution.

您不是要发送请求并等待答复,而是要一直使用异步套接字来发送和接收消息,直到遍历所有要ping的主机,同时检查那些您不希望访问的主机.不能及时得到答复.

Instead of sending a request and waiting for a reply, you really want to use asynchronous sockets to send and receive all the time, until you go through all the hosts you want to ping, while checking for the ones where you didn't get a reply in time.

这篇关于单声道下的C#Ping延迟/缓慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆