.Net 2.0 Ping在长时间运行的系统中失败。 Windows Ping成功

时间:2011-10-24 14:44:11

标签: c# .net windows-xp .net-2.0

我有一个用C#编写的.Net 2.0应用程序监视本地局域网上的其他Windows XP计算机。在某些系统上,经过很长的正常运行时间(40到120天)后,.Net Ping可能会失败。 Windows命令提示符ping仍然成功。

一旦发生此故障,似乎所有.Net Pings都会失败。使用类似代码的单独.Net应用程序也会失败。

以下是代码示例:

internal static bool canPingHost(string host)
{
    bool success = false;
    const int PING_TIMEOUT_MS = 1000;
    try
    {
       using (Ping p = new Ping())
       {
            PingReply pr = p.Send(host, PING_TIMEOUT_MS);
            if (pr.Status == IPStatus.Success)
            {
                success = true;
            }
        }
    }
    catch
    {                
    }
    return success;
}

有关此问题设置的要点:

  • 所有PC都插入到同一个非管理型交换机
  • 所有其他PC都可以使用相同的.Net Ping与问题系统进行通信。
  • Windows ping在问题系统上正常运行。
  • 在问题系统上尝试的任何.Net 2.0应用程序都失败了。
  • 进出问题系统的数据库操作也起作用(TCP连接)
  • 停止并启动应用程序无法解决问题系统上的问题。

当这个系统出现故障时,我会运行另一个带有进一步调试信息的应用程序。

static string doping(IPAddress IP)
{
    int PING_TIMEOUT_MS = 3000;
    string rv = IP.ToString();

    using (Ping p = new Ping())
    {
        bool success = false;
        PingReply pr = null;
        try
        {
            pr = p.Send(IP, PING_TIMEOUT_MS);
            success = pr.Status == IPStatus.Success;
        }
        catch (Exception ex)
        {
            rv = rv +" [ " +ex.Message + " ] ";
        }

        if (pr != null)
        {
            if (success)
            {
                rv = rv + " yes " + pr.RoundtripTime.ToString();
            }
            else
            {
                rv = rv + " no " + pr.Status.ToString();
            }
        }
        else
        {
            rv = rv + " no (fail) ";
        }
    }
    return rv;
}

该计划的输出为192.168.0.2 no 1450 PingReply状态变量返回 1450 ,似乎未在IPStatusPingReply.Status)枚举中定义。

重新启动问题计算机后,.Net Ping再次开始正常工作

看起来存在某些描述的资源问题。我不确定它可能是哪种资源。

我已经阅读过有关异步Pings和.Net 2.0的问题。这是一个同步ping,据我所知它没有受到影响。

我正在寻找:

  • 首先预防问题
  • 一旦失败就调试远程系统的建议(生产系统,Windows XP SP3,未安装开发人员工具)
  • 监控资源以确定哪一个失败。

警告:

  • 目前无法定期重新启动问题系统。
  • 升级到最新版本的.Net Framework目前不是一种选择。
  • 将软件更改为不再使用.Net Ping是一个选项,但我仍然想知道发生了什么。

2 个答案:

答案 0 :(得分:1)

在同一系统上运行的另一个应用程序正在消耗大量(> 100 MB)池非分页字节。这发生在几个星期的时间里。

这是通过查看整个系统的性能计数器来确定的。脱颖而出的是:

  • 内存,池非分页字节(涵盖整个计算机)
  • 进程,_Total,池非分页字节(似乎涵盖所有正在运行的进程)
  • 系统上每个正在运行的进程的进程,池非分页字节。

池Nonpaged字节数字非常大,全部集中在一个应用程序中

重新启动其他应用程序导致非分页池内存使用量返回到更低的值。 Ping然后成功完成。缺少非分页池记忆似乎导致Ping失败。

有关池非页面字节的信息可以在页面Pushing the Limits of Windows: Paged and Nonpaged Pool上找到。当系统用完非分页字节时,可以拒绝许多资源分配,从而导致系统极其不稳定。

很不寻常的问题。该决议没有任何与Ping源直接相关的内容。

答案 1 :(得分:0)

您的代码与我用于ping检查机制的代码没什么不同。我从来没有遇到任何问题,但似乎你的问题完全在应用领域之外。我会说一个有缺陷的网卡驱动程序或IP堆栈以某种方式被破坏。

    private static void Main()
    {
        using (var ping = new Ping())
        using (var waiter = new EventWaitHandle(false, EventResetMode.ManualReset))
        {
            var options = new PingOptions { DontFragment = true };
            var now = DateTime.Now;
            var data = now.ToLongDateString() + " " + now.ToLongTimeString();
            var buffer = Encoding.ASCII.GetBytes(data);
            const int Timeout = 120;

            ping.PingCompleted += PingCompleted;
            ping.SendAsync("www.speedtest.net", Timeout, buffer, options, waiter);
            waiter.WaitOne();
        }

        Console.ReadLine();
    }

    /// <summary>
    /// Handles the Ping Completed event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Net.NetworkInformation.PingCompletedEventArgs"/> instance containing
    /// the event data.</param>
    private static void PingCompleted(object sender, PingCompletedEventArgs e)
    {
        if (e.Reply.Status == IPStatus.Success)
        {
            Console.WriteLine("Address: {0}", e.Reply.Address);
            Console.WriteLine("RoundTrip time: {0}", e.Reply.RoundtripTime);
            Console.WriteLine("Time to live: {0}", e.Reply.Options.Ttl);
            Console.WriteLine("Don't fragment: {0}", e.Reply.Options.DontFragment);
            Console.WriteLine("Buffer size: {0}", e.Reply.Buffer.Length);
            Console.WriteLine("Buffer: {0}", Encoding.ASCII.GetString(e.Reply.Buffer));
        }
        else if (e.Error != null)
        {
            Console.WriteLine(e.Error);
        }

        var waitHandle = e.UserState as EventWaitHandle;

        if (waitHandle != null)
        {
            waitHandle.Set();
        }
    }