Ping.SendAsync() returned replay from 0.0.0.0, how

2019-02-23 20:57发布

i have problem with Ping.SendAsync() function in C#. I ping some ip adresses, but some of they are wrong. I need to remove wrong adresses from list. But how, because p_PingCompleted event args.replay.adress is 0.0.0.0? Here is my code:

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

And output is:

Pinging 16.5.4.3...
Ping reply from: 0.0.0.0 has 0 ms.

3条回答
叛逆
2楼-- · 2019-02-23 21:28

I think it has to do how you are using SendAsync(string, object).

At MSDN, it has a pretty good example. Use SendAsync(String, Int32, Byte[], PingOptions, Object) or SendAsync(IPAddress, Int32, Byte[], PingOptions, Object) instead. Follow that example and it should work for you.

查看更多
爷、活的狠高调
3楼-- · 2019-02-23 21:33

In the async call, send the Ping object (or game object, whatever list you're dealing with) as the object state, and then from the ping completed event, just remove that object from the list if the address is invalid.

查看更多
孤傲高冷的网名
4楼-- · 2019-02-23 21:46

You could use the UserState property and a lock to ensure serialized access to 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);
}

Then in your p_PingCompleted handler:

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);
            }
        }
    }
}
查看更多
登录 后发表回答