【问题标题】:Pinging hostnames takes too long (vs Pinging IP addresses)Ping 主机名花费的时间太长(与 Ping IP 地址相比)
【发布时间】:2018-04-14 03:53:04
【问题描述】:

我正在使用异步 Ping 来检查远程计算机是否可用(代码示例来自here)。我将其修改为使用列表而不是 IP 范围。

这很好用 IF 输入是一个 IP 地址列表(300 多个主机为 0.5 秒)。但我需要检查主机名列表,这需要很长时间(300 多台主机需要 30 多秒)。

问题似乎是不可用主机的 DNS 名称解析。有没有办法绕过它?

或者可能是检查计算机是否在线的不同方法(但它必须使用主机名列表作为输入)。

编辑:我使用了他第三次尝试的代码,这就是为什么我直接链接到页面的那个部分。我可能应该更清楚地说明这一点

【问题讨论】:

  • 这就是为什么我链接到页面上的特定部分。认为它比仅仅说“我使用了第三次尝试”更好:)
  • 啊,你做到了,goodo

标签: c# networking ping


【解决方案1】:

解析主机名的 IP 地址必然比直接获得 IP 花费更多的时间。

选项包括:

  1. 并行执行 ping。您链接到的代码示例显示了如何执行此操作,但请确保您使用的是第 3 节“第三次尝试:一个 Ping 来统治他们,一个 Ping 来找到他们”下的代码,而不是早期的模式之一,以防你还没有。
  2. 我猜测您重复执行此 ping。如果是这种情况,请在开始时进行一次 DNS 查找,然后从那时起您可以 ping IP 地址。例如Dns.GetHostAddresses

【讨论】:

  • 我确实使用并行(我编辑了原始帖子)。不确定您所说的重复是什么意思,但我会在每次应用启动时使用它来从列表中过滤掉离线主机。我在计算机上生成各种不同的报告,而那些离线主机确实降低了我的应用程序的速度。我不使用任何数据库来存储主机和应用程序不在后台运行。在那一刻,我只需要一个在线主机列表,以便我可以使用它。使用 getHost “手动”解析名称并将其转换回主机名(输出应该是主机名)甚至比让 Ping 函数自己完成还要慢。
【解决方案2】:

我在三月份写了下面的代码。我有 12 秒的超时时间来完成所有 ping。如果所有 ping 都完成,代码将更快完成。我还为我的 ping 列表使用数据表,并且 ping 响应也进入表中,因此您可以获取每个 ping 的时间和状态(完成或失败)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("IP", typeof(string));
            dt.Columns.Add("TimeOut", typeof(int));
            dt.Columns.Add("Canceled", typeof(bool));
            dt.Columns.Add("Error", typeof(List<string>));
            dt.Columns.Add("Reply", typeof(List<PingReply>));
            dt.Columns.Add("Sent", typeof(int));
            dt.Columns.Add("Received", typeof(int));


            dt.Rows.Add(new object[] { "192.168.1.1", 0, false, null, null, 4, 0 });
            dt.Rows.Add(new object[] { "172.160.1.27", 0, false, null, null, 4, 0 });
            dt.Rows.Add(new object[] { "172.160.1.37", 0, false, null, null, 4, 0 });
            dt.Rows.Add(new object[] { "172.160.1.57", 0, false, null, null, 4, 0 });


            MyPing ping = new MyPing(dt);

            List<PingReply> replies = dt.AsEnumerable().Where(x => x.Field<List<PingReply>>("Reply") != null).Select(x => x.Field<List<PingReply>>("Reply")).SelectMany(x => x).ToList();

            long ShortTime = replies.Min(x => x.RoundtripTime);
        }
    }

    public class MyPing
    {
        static AutoResetEvent waiter = new AutoResetEvent(false);
        const string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        private Object thisLock = new Object();

        DataTable dt;
        Dictionary<string, DataRow> pingDict = new Dictionary<string, DataRow>();
        const int TIMEOUT = 12000;
        public MyPing() { }
        public MyPing(DataTable dtin)
        {
            dt = dtin;

            Console.WriteLine("Haciendo ping a los equipos, no cierre esta ventana... ");



            // Por cada IP se realiza ping y se  agrega a la lista del modelo
            foreach (DataRow item in dt.Rows)
            {
                Ping ping = new Ping();
                string ip = item.Field<string>("IP");
                pingDict.Add(ip, item);
                ping.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
                byte[] buffer = Encoding.ASCII.GetBytes(data);
                PingOptions pingoptns = new PingOptions(128, true);
                Console.WriteLine("send : {0}", ip);
                ping.SendAsync(ip, TIMEOUT, buffer, pingoptns, item);
            }

            waiter.WaitOne();
        }
        private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
        {
            lock (thisLock)
            {

                DataRow row = null;
                try
                {
                    row = e.UserState as DataRow;
                    string sendIP = row.Field<string>("IP");
                    string replyIP = e.Reply.Address.ToString();
                    Console.WriteLine("reply IP : {0}, send IP : {1}", replyIP, sendIP);
                    // If the operation was canceled, display a message to the user.
                    if (e.Cancelled)
                    {
                        row.SetField<bool>("Canceled", true);
                        return;
                    }

                    // If an error occurred, display the exception to the user.
                    if (e.Error != null)
                    {
                        if (row["Error"] == DBNull.Value) row["Error"] = new List<string>();
                        row.Field<List<string>>("Error").Add(e.Error.Message);
                    }
                    if (e.Reply.Status == IPStatus.TimedOut)
                    {
                        row["TimeOut"] = row.Field<int>("TimeOut") + 1;
                    }
                    else
                    {
                        if (row["Reply"] == DBNull.Value) row["Reply"] = new List<PingReply>();
                        row.Field<List<PingReply>>("Reply").Add(e.Reply);
                        row["Received"] = row.Field<int>("Received") + 1;
                    }

                    row["Sent"] = row.Field<int>("Sent") - 1;
                    if (row.Field<int>("Sent") > 0)
                    {
                        Ping ping = new Ping();
                        string ip = row.Field<string>("IP");
                        ping.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
                        byte[] buffer = Encoding.ASCII.GetBytes(data);
                        PingOptions pingoptns = new PingOptions(128, true);
                        Console.WriteLine("send : {0}", ip);
                        ping.SendAsync(ip, TIMEOUT, buffer, pingoptns, row); ;
                    }
                    else
                    {
                        pingDict.Remove(sendIP);
                        if (pingDict.Count == 0) waiter.Set();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception : {0}", ex.Message);
                }
            }
        }
    }

}

【讨论】:

  • 那个地址是如何“但是它必须使用主机名列表作为输入”
  • Ping 使用 IP 地址作为字符串或主机名。
  • Yessss,但不确定这与示例有多大不同。也许按照 Peter 的建议进行一次性查找?
  • 代码进行查找。这就是字典的用途。代码可以 ping 多次,当所有响应发生时,字典会清空,然后设置 AutoResetEvent 以指示结束。
  • 我不认为这是我需要的。我需要使用主机名而不是 IP 地址。我的输入是主机名列表(在线和离线),我的输出也应该是主机名列表(仅限在线)。 Ping 确实适用于 IP 和主机名,但使用主机名要慢得多。这就是这里的问题......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
相关资源
最近更新 更多