none
Ping not returning IP address when destination is unreachable RRS feed

  • Question

  • I'm pinging addresses on my local address to locate computers.  When I ping an address that doesn't have a computer associated with it, the reply Status value is "DestinationHostUnreachable".  All fine and good.  But, the IP address value that is returned is the IP address of my computer, not the address of the computer that I tried pinging!?!  So, in simple terms, when I get the reply back from the call to Ping, I don't know which address that "DestinationHostUnreachable" is associated with.

    Anyone have any suggestions?

    My code is based upon the sample async code example provided in the Microsoft documentation for Ping, https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ping?view=netframework-4.7.2.  The main difference is that in the Main function, I wrapped the code associated with pinging inside of a For loop so that I can scan the range of IP addresses (0 to 255) of the local network.

    Richard

    Tuesday, October 1, 2019 9:55 PM

Answers

  • Did you know that you can pass anything as UserState in the SendAsync method? This includes a custom class that hold the original address you're pinging for.

    using System;
    using System.Text;
    using System.Net;
    using System.Net.NetworkInformation;
    using System.ComponentModel;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class PingTest
        {
            class PingState
            {
                public string IPAddr { get; set; }
                public AutoResetEvent waiter { get; set; }
            }
    
            public static void SendPing(string who)
            {
                PingState state = new PingState();
    
                state.waiter = new AutoResetEvent(false);
                state.IPAddr = who;
    
                Ping pingSender = new Ping();
    
                // When the PingCompleted event is raised,
                // the PingCompletedCallback method is called.
                pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
    
                // Create a buffer of 32 bytes of data to be transmitted.
                string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
                byte[] buffer = Encoding.ASCII.GetBytes(data);
    
                // Wait 12 seconds for a reply.
                int timeout = 12000;
    
                // Set options for transmission:
                // The data can go through 64 gateways or routers
                // before it is destroyed, and the data packet
                // cannot be fragmented.
                PingOptions options = new PingOptions(64, true);
    
                Console.WriteLine("Time to live: {0}", options.Ttl);
                Console.WriteLine("Don't fragment: {0}", options.DontFragment);
    
                // Send the ping asynchronously.
                // Use the waiter as the user token.
                // When the callback completes, it can wake up this thread.
                pingSender.SendAsync(who, timeout, buffer, options, state);
    
                // Prevent this example application from ending.
                // A real application should do something useful
                // when possible.
                state.waiter.WaitOne();
                Console.WriteLine("Ping example completed.");
            }
    
            private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
            {
                PingState state = (PingState)e.UserState;
                // If the operation was canceled, display a message to the user.
                if (e.Cancelled)
                {
                    Console.WriteLine("Ping canceled.");
    
                    // Let the main thread resume. 
                    // UserToken is the AutoResetEvent object that the main thread 
                    // is waiting for.
                    ((AutoResetEvent)state.waiter).Set();
                }
    
                // If an error occurred, display the exception to the user.
                if (e.Error != null)
                {
                    Console.WriteLine("Ping failed:");
                    Console.WriteLine(e.Error.ToString());
    
                    // Let the main thread resume. 
                    ((AutoResetEvent)state.waiter).Set();
                }
    
                PingReply reply = e.Reply;
    
                DisplayReply(reply, state.IPAddr);
    
                // Let the main thread resume.
                ((AutoResetEvent)state.waiter).Set();
            }
    
            public static void DisplayReply(PingReply reply, string IPAddr)
            {
                if (reply == null)
                    return;
    
                Console.WriteLine("ping status: {0}", reply.Status);
                //if (reply.Status == IPStatus.Success)
                {
                    //Console.WriteLine("Address: {0}", reply.Address.ToString());
                    Console.WriteLine("Address: {0}", IPAddr);
                    Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
                    if (reply.Options != null)
                    {
                        Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                        Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                    }
                    Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
                }
            }
    
        }
    }


    • Marked as answer by RichardR Wednesday, October 2, 2019 2:27 AM
    • Edited by cheong00Editor Friday, October 11, 2019 6:57 AM Missed one change to "state.waiter" in PingCompletedCallback
    Wednesday, October 2, 2019 2:09 AM
    Answerer

All replies

  • You launched the ping command, so you should know what IP you're ping-ing for, why read the output to get it at all?
    Wednesday, October 2, 2019 1:30 AM
    Answerer
  • Hi,

    That is a comms issue.  What is the source and destination IP? It sounds like they are on different layer 2 networks with no route.

    On the machine you're on (windows) run ipconfig via cmd or Linux run ip -a and post output plus the IP you're trying to ping.

    Thanks,
    Matt

    Wednesday, October 2, 2019 1:35 AM
  • Hi RichardR,

    Thank you for posting here.

    I test the code in the MS document, all works well. I add the IPV4 addresses in the args arrays like below.

    args = new string[2] { "xxx.xx.xx.xxx","xxx.xx.xx.xxx" };

    Local address:

    Remote computer ip address:

    I do not get the "DestinationHostUnreachable", please provide more details.

    >>  The main difference is that in the Main function, I wrapped the code associated with pinging inside of a For loop so that I can scan the range of IP addresses (0 to 255) of the local network.

    Use a foreach to do the loop. Here is the code for your reference.

      static void Main(string[] args)
            {
                args = new string[2] { "xxx.xx.xx.xxx", "xxx.xx.xx.xxx"};
    
                if (args.Length == 0)
                    throw new ArgumentException("Ping needs a host or IP Address.");
    
                foreach (var item in args)
                {
                    string who = item;
                    AutoResetEvent waiter = new AutoResetEvent(false);
    
                    Ping pingSender = new Ping();
    
                    // When the PingCompleted event is raised,
                    // the PingCompletedCallback method is called.
                    pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
    
                    // Create a buffer of 32 bytes of data to be transmitted.
                    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
                    byte[] buffer = Encoding.ASCII.GetBytes(data);
    
                    // Wait 12 seconds for a reply.
                    int timeout = 12000;
    
                    // Set options for transmission:
                    // The data can go through 64 gateways or routers
                    // before it is destroyed, and the data packet
                    // cannot be fragmented.
                    PingOptions options = new PingOptions(64, true);
    
                    Console.WriteLine("Time to live: {0}", options.Ttl);
                    Console.WriteLine("Don't fragment: {0}", options.DontFragment);
    
                    // Send the ping asynchronously.
                    // Use the waiter as the user token.
                    // When the callback completes, it can wake up this thread.
                    pingSender.SendAsync(who, timeout, buffer, options, waiter);
    
                    // Prevent this example application from ending.
                    // A real application should do something useful
                    // when possible.
                    waiter.WaitOne();
                    Console.WriteLine("Ping example completed.");
    
                }
                Console.ReadLine();
    
            }
    
            private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
            {
                // If the operation was canceled, display a message to the user.
                if (e.Cancelled)
                {
                    Console.WriteLine("Ping canceled.");
    
                    // Let the main thread resume. 
                    // UserToken is the AutoResetEvent object that the main thread 
                    // is waiting for.
                    ((AutoResetEvent)e.UserState).Set();
                }
    
                // If an error occurred, display the exception to the user.
                if (e.Error != null)
                {
                    Console.WriteLine("Ping failed:");
                    Console.WriteLine(e.Error.ToString());
    
                    // Let the main thread resume. 
                    ((AutoResetEvent)e.UserState).Set();
                }
    
                PingReply reply = e.Reply;
    
                DisplayReply(reply);
    
                // Let the main thread resume.
                ((AutoResetEvent)e.UserState).Set();
            }
    
            public static void DisplayReply(PingReply reply)
            {
                if (reply == null)
                    return;
    
                Console.WriteLine("ping status: {0}", reply.Status);
                if (reply.Status == IPStatus.Success)
                {
                    Console.WriteLine("Address: {0}", reply.Address.ToString());
                    Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
                    Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                    Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                    Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
                }
            }

    Result:

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Wednesday, October 2, 2019 1:52 AM
    Moderator
  • Wendy,

    Thank you for replying and trying to replicate the issue. 

    But, did you try pinging an address that doesn't have anything assigned to it?  I'm pinging every possible address on the local network (xxx.xxx.xxx.000 to xxx.xxx.xxx.254).  Obviously, most of those addressed are not associated with any devices.  Those are the addresses which are generating "DestinationHostUnreachable", as is totally expected.

    So as I'm going through all the possible IP addresses, I try to ping xxx.xxx.xxx.123 for example, and there's no device with that address.  So, as expected, Ping returns with the ""DestinationHostUnreachable" status.  But the Address field that is returned is not xxx.xxx.xxx.123, but instead my computer's IP address. 

    So, how do I know by checking the results that the program was trying to ping xxx.xxx.xxx.123 and that it failed when the results contains my computer's IP address?

    Richard

    Wednesday, October 2, 2019 2:08 AM
  • Did you know that you can pass anything as UserState in the SendAsync method? This includes a custom class that hold the original address you're pinging for.

    using System;
    using System.Text;
    using System.Net;
    using System.Net.NetworkInformation;
    using System.ComponentModel;
    using System.Threading;
    
    namespace ConsoleApp1
    {
        class PingTest
        {
            class PingState
            {
                public string IPAddr { get; set; }
                public AutoResetEvent waiter { get; set; }
            }
    
            public static void SendPing(string who)
            {
                PingState state = new PingState();
    
                state.waiter = new AutoResetEvent(false);
                state.IPAddr = who;
    
                Ping pingSender = new Ping();
    
                // When the PingCompleted event is raised,
                // the PingCompletedCallback method is called.
                pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
    
                // Create a buffer of 32 bytes of data to be transmitted.
                string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
                byte[] buffer = Encoding.ASCII.GetBytes(data);
    
                // Wait 12 seconds for a reply.
                int timeout = 12000;
    
                // Set options for transmission:
                // The data can go through 64 gateways or routers
                // before it is destroyed, and the data packet
                // cannot be fragmented.
                PingOptions options = new PingOptions(64, true);
    
                Console.WriteLine("Time to live: {0}", options.Ttl);
                Console.WriteLine("Don't fragment: {0}", options.DontFragment);
    
                // Send the ping asynchronously.
                // Use the waiter as the user token.
                // When the callback completes, it can wake up this thread.
                pingSender.SendAsync(who, timeout, buffer, options, state);
    
                // Prevent this example application from ending.
                // A real application should do something useful
                // when possible.
                state.waiter.WaitOne();
                Console.WriteLine("Ping example completed.");
            }
    
            private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
            {
                PingState state = (PingState)e.UserState;
                // If the operation was canceled, display a message to the user.
                if (e.Cancelled)
                {
                    Console.WriteLine("Ping canceled.");
    
                    // Let the main thread resume. 
                    // UserToken is the AutoResetEvent object that the main thread 
                    // is waiting for.
                    ((AutoResetEvent)state.waiter).Set();
                }
    
                // If an error occurred, display the exception to the user.
                if (e.Error != null)
                {
                    Console.WriteLine("Ping failed:");
                    Console.WriteLine(e.Error.ToString());
    
                    // Let the main thread resume. 
                    ((AutoResetEvent)state.waiter).Set();
                }
    
                PingReply reply = e.Reply;
    
                DisplayReply(reply, state.IPAddr);
    
                // Let the main thread resume.
                ((AutoResetEvent)state.waiter).Set();
            }
    
            public static void DisplayReply(PingReply reply, string IPAddr)
            {
                if (reply == null)
                    return;
    
                Console.WriteLine("ping status: {0}", reply.Status);
                //if (reply.Status == IPStatus.Success)
                {
                    //Console.WriteLine("Address: {0}", reply.Address.ToString());
                    Console.WriteLine("Address: {0}", IPAddr);
                    Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
                    if (reply.Options != null)
                    {
                        Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                        Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                    }
                    Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
                }
            }
    
        }
    }


    • Marked as answer by RichardR Wednesday, October 2, 2019 2:27 AM
    • Edited by cheong00Editor Friday, October 11, 2019 6:57 AM Missed one change to "state.waiter" in PingCompletedCallback
    Wednesday, October 2, 2019 2:09 AM
    Answerer
  • cheong00,

    Ah, thank you!!  Your solution completely slipped my mind.

    Richard

    Wednesday, October 2, 2019 2:28 AM