.NET Ping()给出错误的超时?

时间:2014-03-29 01:12:04

标签: c# .net network-programming ping

我有一个循环的脚本,每秒向主机发送一次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());
}

4 个答案:

答案 0 :(得分:1)

如果您的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

答案 1 :(得分:1)

我可能已经弄清楚了。我正在使用相关机器的netbios名称。我猜测每次进行ping操作都会考虑到往返的IP查找并超时。当我只使用IP时,它运行得很好并且没有超时。

感谢您的投入。

答案 2 :(得分:0)

在我的例子中,字节数组大小是主要原因(我编写了类似的ping应用程序)

何时

var buffer = new byte[65500];
  

2014/3/30 11:29:26   8.8.8.8:TimedOut(0ms)

更改为

var buffer = new byte[32];
  

2014/3/30 11:32:50   8.8.8.8:成功(8ms)

我推断ping缓冲区如果太高,那么ICMP echo消息可能被分段成为多个数据包然后只发送出去,因此它无法在超时期限内完成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回复的超时(ms)...

答案 3 :(得分:0)

我看到的行为与OP相同。我的ping.Send()只发送一个byte [30]的缓冲区,并且总是使用显式IP,所以不涉及DNS / NetBIOS。我尝试了不同的超时值,但从命令行使用ping时,始终看到Send()与零超时的常规超时返回。

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");
}