.NET Ping()是否会出现虚假超时?

7
我有一个脚本,每秒钟循环一次并向主机发送ping。其目的是测试我家网络的无线性能。问题是,我的脚本似乎会出现超时,而客户端(pingER和pingEE)上的标准“ping -t”没有这样的超时。事实上,在过去的30分钟中,两者都没有超时,而我的脚本每隔几分钟就会收到超时回复。
以下是我的基本脚本。在所有情况下,当发生这种情况时,我的回复是TimedOut,并且响应时间为0ms。我的脚本是否导致了虚假超时?谢谢。
编辑:更新代码以反映最新更改,仍然具有相同的行为。
while (true)
{
    System.Threading.Thread.Sleep(delay);
    var builder = new StringBuilder();

    hosts.ForEach(h =>
    {
        var buffer = new byte[32];
        var reply = ping.Send(h, 4000, buffer, new PingOptions(600, true));
        var error = reply.Status != IPStatus.Success || reply.RoundtripTime > maxRoundTrip;

        if (verbose || error)
        {
            builder.AppendFormat("{0}: {1} ({2}ms)", h, reply.Status, reply.RoundtripTime);
            builder.Append(Environment.NewLine);

            if (error)
            {
                WriteLog(h, reply);
                SendEmail(h, reply);
            }
        }
    });

    Console.WriteLine(DateTime.Now);
    Console.WriteLine(builder.ToString());
}

哪个错误条件出现了问题? 1000毫秒的响应时间应该足够长,但是你没有使用标准ping的特殊原因吗? - BradleyDotNET
我使用这个程序是因为我想让它运行并在出现错误时提醒我并记录日志。然而,在我的情况下,它似乎不太可靠,或者我做错了什么。在同一台机器上运行CMD ping.exe却没有任何超时。 - Ryan Peters
4个回答

2
如果您的ping -t超时值小于1000或maxRoundTrip的值小于1000,则在两个不同的ping(.NET Ping.Send vs. ping -t)中检查了不同的超时。默认的Windows ping超时时间为4000毫秒。http://technet.microsoft.com/en-us/library/bb490968.aspx 此外,在您的.NET代码中,您正在发送最大缓冲区大小为65500字节。默认的Windows ping命令只发送32字节的数据。
因此,超时或缓冲区大小之间的差异可能是导致变化的原因。
有关.NET Ping.Send方法的更多信息:http://msdn.microsoft.com/en-us/library/ms144956(v=vs.110).aspx

你使用了哪些选项来比较 ping -t 命令?并且你在什么类型的应用程序中运行 .NET 的 Ping.Send(网站/IIS、命令行工具、WinForms)?如果是 IIS,那么你可以检查应用程序池的回收时间。 - BateTech
你正在使用哪个版本的.NET?而且你是否增加了ping.send超时和maxRoundTrip超时值? - BateTech
CMD ping 命令只是 "ping <主机名> -t"。该应用程序是一个运行在我的桌面计算机上的 c# 4.5 控制台应用程序。我从其他计算机上运行它时得到相同的结果。 - Ryan Peters
Ping状态为超时。我尝试了您的建议,仍然会出现随机超时。此外,我已经同时运行标准CMD ping超过一个小时,没有出现任何超时。 - Ryan Peters
此外,似乎总是无线笔记本电脑超时。如果 ping.exe 和我的脚本都超时了,这就有意义了,但只有我的脚本超时了。Ping.exe 还没有超时,我已经让它运行了几个小时。 - Ryan Peters
显示剩余4条评论

2

我可能已经找到解决方法了。我之前在使用该机器的NetBIOS名称。我猜每次ping时,它都会计算IP查找的往返时间,并超时。当我只使用IP时,它工作得很好,没有超时。

感谢您的帮助。


请问您如何在C#中使用define netbios name?或者您能否向我展示如何在程序中定义'h'?谢谢。 - V-SHY
很高兴听到你解决了!是的,这很有道理,因为“ping -t”仅在第一次ping之前执行了一次nslookup,但.NET代码将在每次迭代中执行查找(除非幕后有某种DNS缓存机制)。@V-SHY,通过“netbios”名称,他只是指他正在使用FQDN而不是IP地址;而'h'在'ForEach' lambda表达式中被定义为第一个变量。 - BateTech

0

我看到与OP相同的行为。我的ping.Send()仅发送大小为byte [30]的缓冲区,并始终使用显式IP,因此不涉及DNS / NetBIOS。我尝试了不同的超时值,但始终从Send()看到定期的超时返回,而从命令行使用ping时则没有超时。

public PingCheck(string address, int timeout = 250, int pingNbr = 1)
{
    var rtn = IPAddress.TryParse(address, out IPAddress addr);
    if (rtn)
    {
        IpAddress = addr;

        var dataSend = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        var pinger = new Ping();
        var pingerOptions = new PingOptions();
        pingerOptions.DontFragment = true;
        var buffer = Encoding.ASCII.GetBytes(dataSend);

        var statusList = new List<IPStatus>();
        var lossList = new List<bool>();
        var tripList = new List<long>();

        for (int i=0; i<pingNbr; i++)
        {
            var pingerReply = pinger.Send(addr, timeout, buffer, pingerOptions);
            var bufback = pingerReply.Buffer;
            var dataBack = Encoding.ASCII.GetString(bufback);

            var status = pingerReply.Status;
            var loss = (dataSend != dataBack);
            var msecs = pingerReply.RoundtripTime;

            statusList.Add(status);
            lossList.Add(loss);
            tripList.Add(msecs);
        }

       // TODO: Add statistics check
    }
    else
        throw new PingException("No IP Address");
}

0
在我的情况下,字节数组的大小是主要原因(我编写了一个类似的ping应用程序)。
当...
var buffer = new byte[65500];

2014年3月30日11:29:26 8.8.8.8:超时(0毫秒)
var buffer = new byte[32];

2014/3/30 11:32:50 8.8.8.8:成功(8毫秒)
我推断如果ping缓冲区太高,则ICMP回显消息可能会被分段成多个数据包,然后才发送出去,因此无法在超时期间完成ping。(但似乎OP在答案中提到这是主机名解析问题,那么我的推断可能是错误的)
我的示例代码
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            int delay = 1000;
            Ping ping = new Ping();
            //OP using something else?
            System.Net.IPAddress h = IPAddress.Parse("8.8.8.8");

            while (true)
            {
                System.Threading.Thread.Sleep(delay);
                var builder = new StringBuilder();

                    //change buffer size change the result...
                    //var buffer = new byte[65500];
                    var buffer = new byte[32];
                    var reply = ping.Send(h, 1000, buffer, new PingOptions(600, false));
                    var error = reply.Status != IPStatus.Success || reply.RoundtripTime > 3000;

                    if (error)
                    {
                        builder.AppendFormat("{0}: {1} ({2}ms)", h, reply.Status, reply.RoundtripTime);
                        builder.Append(Environment.NewLine);
                    }
                    else
                    {
                        builder.AppendFormat("{0}: {1} ({2}ms)", h, reply.Status, reply.RoundtripTime);
                    }

                Console.WriteLine(DateTime.Now);
                Console.WriteLine(builder.ToString());
            }
        }
    }
}

var reply = ping.Send(h, 1000, buffer, new PingOptions(600, false));

1000是ping回复的超时时间(毫秒)...


“delay”设置为1000毫秒。我已经改变了Send调用的超时时间,但结果相同。 - Ryan Peters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接