首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#平延迟/慢在单点下

问C#平延迟/慢在单点下
EN

Stack Overflow用户
提问于 2015-03-17 08:08:31
回答 1查看 2.2K关注 0票数 1

在Mono3.2.8下运行的Ping.Send在C# .Net 4.5中遇到了延迟问题。我的代码如下所示:

代码语言:javascript
复制
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下运行上述代码的输出是:

  1. 预平: 03/17/2015 15:43:21
  2. 邮政平: 03/17/2015 15:43:41
  3. 成功!RTT: 2
  4. 预平: 03/17/2015 15:43:41
  5. 邮政点播: 03/17/2015 15:44:01
  6. 成功!RTT: 46

您可以看到,在"Pre“和"Post”时间戳之间,延迟了20秒(这是一致的,总是20秒)。运行Mono的机器在相同的172.16.1.*网络上,我把Google放在那里进行额外的测试。

在我的Windows机器上本地运行相同的代码会产生以下输出(pings不会延迟):

  1. 预审: 17/03/2015 3:38:21
  2. 邮政点播: 17/03/2015 3:38:21
  3. 成功!RTT: 3
  4. 预审: 17/03/2015 3:38:21
  5. 邮政点播: 17/03/2015 3:38:21
  6. 成功!RTT: 46

对这里发生了什么有什么想法吗?我需要敲击数百台机器,所以延迟20秒是不能接受的。

更新:我尝试在下面的代码中使用Ping.SendAsync方法:

代码语言:javascript
复制
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秒。不过还是不太理想。

EN

回答 1

Stack Overflow用户

发布于 2015-03-17 08:43:38

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

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

首先,您可能需要检查哪些是实际发生的。当您尝试执行pings时,ping会执行吗?如果你sudo你的应用程序,它会有帮助吗?

默认的超时时间是4秒,所以它不应该花费20秒--在此之前您应该有一个超时时间。并且您显式地传递了60毫秒的超时。

所有这些(以及对Mono中的代码处理pings的仔细查看)都表明了以下几点:

  • Ping类本身的初始设置需要20,000--查询功能、查找ping等。显然不是这样,因为您正在尝试两个ping,每个都要花很长时间。
  • 大部分时间是在实际的ICMP/ping代码之外度过的。最有可能出现的地方是Dns.GetHostName或Dns.GetHostAddresses。分别检查这两个选项和ping本身。
  • 其他一些线程/进程正在干扰您自己的ping操作。ICMP套接字将获得所有ICMP响应,因为ICMP中没有端口等概念。

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

与发送请求和等待回复不同,您实际上希望始终使用异步套接字来发送和接收,直到您遍历所有要ping的主机,同时检查没有及时收到答复的主机。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29094041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档