Ping.SendAsync()返回了来自0.0.0.0的回复,如何获取被ping的地址?

4

我在C#中使用Ping.SendAsync()函数遇到了问题。 我ping一些IP地址,但其中一些是错误的。我需要从列表中删除错误的地址。但是如何操作呢?因为p_PingCompleted事件参数replay.adress是0.0.0.0? 以下是我的代码:

System.Collections.Generic.List<Game> GameList = new System.Collections.Generic.List<Game>();
System.Timers.Timer timer = new System.Timers.Timer(5000);

        public StartServer()
        {
            this.tcpListener = new TcpListener(IPAddress.Any, 8888);
            this.listenThread = new Thread(new ThreadStart(ListenForClients));
            this.listenThread.Start();
            Console.WriteLine("Master server running...");
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Start();
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Game[] games = GameList.ToArray();
            foreach (Game curgame in games)
            {
                System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping();
                p.PingCompleted += new System.Net.NetworkInformation.PingCompletedEventHandler(p_PingCompleted);
                p.SendAsync(IPAddress.Parse(curgame.IP), new object());
            }
            SendMessageToAll(output);
            Console.WriteLine("Timer.Elapsed with data [" + output + "]");
        }

        void p_PingCompleted(object sender, System.Net.NetworkInformation.PingCompletedEventArgs e)
        {
            Console.WriteLine("Ping reply from: " + e.Reply.Address.ToString() + " has " + e.Reply.RoundtripTime.ToString() + " ms.");
            if (e.Reply.RoundtripTime == 0 ||
                e.Reply.RoundtripTime >= 2500)
            {
                Console.WriteLine("   Removing this server because ping is 0 or is greater than 2500 ms");
            }
        }

输出结果为:

Pinging 16.5.4.3...
Ping reply from: 0.0.0.0 has 0 ms.
3个回答

2
你可以使用UserState属性和一个锁来确保对GameList的串行访问:
byte[] buffer = Encoding.ASCII.GetBytes (new string('a', 32));
var options = new PingOptions (32, true);

Ping p = new Ping();
p.PingCompleted += p_PingCompleted;
foreach (Game curgame in GameList.ToArray())
{
    // e.UserState will be curgame
    p.SendAsync(IPAddress.Parse(curgame.IP), 2500, buffer, options, curgame);
}

然后在您的 p_PingCompleted 处理程序中:

void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
    var game = (Game)e.UserState;
    if (e.Reply.Status != IPStatus.Success)
    {
        Console.WriteLine(
            "  Could not reach {0} ({1}), removing this server...",
            game.IP,
            e.Reply.Status);
        lock (GameList)
        {
            GameList.Remove(game);
        }
    }
    else
    {
        Console.WriteLine(
            "Ping reply from: {0} in {1} ms",
            e.Reply.Address,
            e.Reply.RoundtripTime);
        if (e.Reply.RoundtripTime == 0 ||
            e.Reply.RoundtripTime >= 2500)
        {
            Console.WriteLine("  Ping too high, removing this server...");
            lock (GameList)
            {
                GameList.Remove(game);
            }
        }
    }
}

这很好,但它没有解释为什么他的IP地址会显示为0.0.0.0。 - user195488
@0A0D:我敢打赌,在这种情况下 PingReply.Status 大概会像目标不可达一样。 - user7116

1
在异步调用中,将Ping对象(或游戏对象,无论你正在处理哪个列表)作为对象状态发送,并且从ping完成事件中,如果地址无效,只需从列表中删除该对象即可。

你的意思是 p.SendAsync(IPAddress.Parse(curgame.IP), curgame); 吗? - Matej Kormuth
是的。只需在ping完成的代码中使用GamesList.Remove(e.UserState); - Can Poyrazoğlu

0

我认为这与你如何使用SendAsync(string, object)有关。

MSDN上,有一个非常好的例子。改用SendAsync(String, Int32, Byte[], PingOptions, Object)或者SendAsync(IPAddress, Int32, Byte[], PingOptions, Object)。按照那个例子操作应该可以解决问题。


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