Ping a domain name or Ipv6 address

I’m not having much luck trying to find a solution to Ping a domain name that is cross platform.

  • UnityEngine.Ping does not appear to support domain names, only IPs.
  • System.Net.NetworkInformation.Ping works in the editor but results in “InvalidOperationException: No process is associated with this object” on Android.
  • I have not tested iOS yet.

Android Error Log

InvalidOperationException: No process is associated with this object.
08-16 13:57:06.591 27339 27391 E Unity : at System.Diagnostics.Process.EnsureState (System.Diagnostics.Process+State state) [0x00000] in <00000000000000000000000000000000>:0
08-16 13:57:06.591 27339 27391 E Unity : at System.Diagnostics.Process.get_HasExited () [0x00000] in <00000000000000000000000000000000>:0
08-16 13:57:06.591 27339 27391 E Unity : at System.Net.NetworkInformation.Ping.SendUnprivileged (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) [0x00000] in <00000000000000000000000000000000>:0
08-16 13:57:06.591 27339 27391 E Unity : at System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) [0x00000] in <00000000000000000000000000000000>:0
08-16 13:57:06.591 27339 27391 E Unity : at System.Net.NetworkInformation.Ping.Send (System.String hostNameOrAddress, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) [0x00000] in <00000000000000000000000000000000>:0
08-16 13:57:06.591 27339 27391 E Unity : at System.Net.NetworkInformation.P

Is there any other alternatives? I need to get the round trip time from various domain names on Android and iOS. Perhaps it’s worth considering doing this in two steps, get IP from domain name then using UnityEngine.Ping to get round trip time?

//Works in Editor
//Errors on Android
System.Net.NetworkInformation.Ping oregon = new System.Net.NetworkInformation.Ping();
var oregonTask = oregon.SendPingAsync("gamelift.us-west-2.amazonaws.com");
await oregonTask.ContinueWith((task) =>
{

});

//Works in Editor
//Errors on Android
System.Net.NetworkInformation.Ping oregon = new System.Net.NetworkInformation.Ping();
var test = oregon.Send("gamelift.us-west-2.amazonaws.com");

while(test.Status != IPStatus.Success)
{
   yield return null;
}
1 Like

I am able to successfully get the ping time on Android if I use UnityEngine.Ping instead. This does require me to look up the IP first. Assuming this works on iOS this is a nice fallback for the moment. But … I’d really like to understand why using .Net for DNS lookup works but not for the Ping. Was really hoping for everything to be async since there is going to be multiple request made.

System.Net.IPHostEntry myHost = System.Net.Dns.GetHostEntry("gamelift.us-west-2.amazonaws.com");
string myIp = myHost.AddressList[0].ToString();

UnityEngine.Ping pingReply = new UnityEngine.Ping(myIp);
while(pingReply.isDone == false)
{
    yield return null;
}

Debug.Log("GetAwsRegionPingData - Oregon: " + pingReply.time);

Edit: Thinking on this some more, I’m not sure dns lookup returning ipv4 address to use with UnityEngine.Ping is ideal. I forgot iOS requires support for ipv6 only networks. Which implies I can’t manually pass in the ipv4 address. I’d prefer if I didn’t have to map ipv4 to 6 every time, especially when I’m already starting with the domain.

So I decided to try mapping from ipv4 to ipv6 since I already had this working for match join logic. Unfortunately I’ve discovered that UnityEngine.Ping does not like Ipv6 addresses in general, let alone mapped addresses. I tried both my local ipv6 address and mapped address and both never complete, isDone never returns as true.

To double check I pinged both ipv6 addresses through windows command prompt without issue. Both returned correctly and included round trip time.

So… not sure what to do here. What little I’ve been able to glean from google seems to imply System.Net.NetworkInformation.Ping may not work on iOS or Android and UnityEngine.Ping does not support ipv6 addresses.

If anyone knows of another alternative I’d be very interested.

//Get the IP from domain name
IPHostEntry myHost = Dns.GetHostEntry("gamelift.us-west-2.amazonaws.com");
string myIp = myHost.AddressList[0].ToString();

if (myHost.AddressList.Length >= 1 && !String.IsNullOrEmpty(myIp))
{
    //Map the ipv4 address to ipv6
    IPAddress newAddress = IPAddress.Parse(myIp);
    if (newAddress.IsIPv4MappedToIPv6 == false)
    {
        IPAddress myipv6Address = newAddress.MapToIPv6();
        myIp = myipv6Address.ToString();
    }

    //Ping the Ip
    UnityEngine.Ping pingReply = new UnityEngine.Ping(myIp);
    while (pingReply.isDone == false)
    {
        yield return null;
        Debug.Log("GetAwsRegionPingData...");
    }

    Debug.LogError("GetAwsRegionPingData - Oregon: " + pingReply.time);
}

I did come across a support ticket for UnityEngine.Ping and ipv6. It is marked as fixed in 5.4.1 yet doesn’t seem to work. I re-attempted with google.com ipv6 address and it never completes. Anyone else able to use this with ipv6 addresses? I’m not having much luck finding an alternative for either of these issues.

System.Net.IPHostEntry googleHostEntry = System.Net.Dns.GetHostEntry("google.com");
string googleIP = googleHostEntry.AddressList[0].ToString();
Debug.LogError("Google IP: " + googleIP);

UnityEngine.Ping pingReply = new UnityEngine.Ping(googleIP);
while (pingReply.isDone == false)
{
    yield return null;
    Debug.Log("GetAwsRegionPingData...");
}

Debug.LogError("GetAwsRegionPingData - Google - Ip: " + pingReply.ip + "  RTT: " + pingReply.time);

Still no luck on this. I tried a few different options. Timing the sending of a web request. Unfortunately that takes a significant amount of time, multiple seconds vs 30ms ping time. I’m sure it doesn’t help that the domain actively blocks this as well, so it errors out on top of that. Additionally I tried opening a socket connection and timing that manually as well. That also takes much longer than anticipated.

As such I decided to mess around with Ping some more and noticed System.Net.NetworkInformation.Ping also errors out on desktop but only with Ipv6 addresses. I’m curious if this is why UnityEngine.Ping never completes with Ipv6 as well. Perhaps they are the same issue and I just don’t see the exception with Unitys.

Error Message

SocketException: An address incompatible with the requested protocol was used.

System.Net.Sockets.Socket.SendTo (System.Byte[ ] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) (at :0)
System.Net.Sockets.Socket.SendTo (System.Byte[ ] buffer, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) (at :0)
System.Net.NetworkInformation.Ping.SendPrivileged (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) (at :0)
System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) (at :0)
System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer) (at :0)
System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address, System.Int32 timeout) (at :0)
System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address) (at :0)
(wrapper remoting-invoke-with-check) System.Net.NetworkInformation.Ping.Send(System.Net.IPAddress)

IPHostEntry myHost = Dns.GetHostEntry("google.com");

System.Net.NetworkInformation.Ping myPing = new System.Net.NetworkInformation.Ping();
var pingReply = myPing.Send(myHost.AddressList[0]);
if (pingReply.Status == IPStatus.Success)
{
    Debug.LogError("GetAWSRegionPingData " + pingReply.RoundtripTime);
}
else
{
    Debug.LogError("GetAWSRegionPingData " + pingReply.Status);
}

System.Net.NetworkInformation.Ping should be compatible with Ipv4, Ipv6 and Domain names from what I understand, so it makes no sense that is is also failing on desktop.

The plot thickens…

Ran out of ideas so decided why not just try UnityEngine.Ping on android with Ipv6 address and see what happens. I was curious if it would give the same error as the System.Net.NetworkInformation.Ping. I was also wondering if this could be a local network / router issue. This would allow me to switch to cellular and see if there were any changes.

Miraculously it works, no cellular needed. What…

I am able to ping “google.com” at Ipv6 address “2607:f8b0:4005:80a::200e”. Round trip time of 17ms.

However… Re-running this in the editor results in infinite loop and isDone is never set to true. I had build settings set to Android though, so I switched platforms back to windows to double check. Still doesn’t work. Build standalone version and re-checked in case it’s just the editor… still doesn’t work.

Unity or Windows issue perhaps? I can ping through command prompt no problem. Firewall? Admin… hmm…

IPHostEntry myHost = Dns.GetHostEntry("google.com");
string myIp = myHost.AddressList[0].ToString();
UnityEngine.Ping myPing = new UnityEngine.Ping(myIp);
      
while(myPing.isDone == false)
{
    Debug.Log("GetAWSRegionPingData waiting..." + myIp);
    yield return null;
}

Debug.LogError("GetAWSRegionPingData " + myIp +" RTT:" + myPing.time);

Hit more snags on mobile unfortunately.

Mapping the Ipv4 to Ipv6 on Android results in the following error message when using UnityEngine.Ping: “Ping address is IPv4 mapped to IPv6, but we do not handle mapped addresses.

Which is a bummer, as I’m stuck with Ipv4. Surprised this doesn’t work, yet Unet handles mapped addresses just fine when connecting to a game server.

So I’m pretty much out of options other than to go with Ipv4 on mobile and cross my fingers. I’m hoping I can make it through iOS review with this since I can include some default values and nothing using this ping data will fail later on down the pipe.

I don’t know enough about Ipv6 only networks to know if this will actually cause problems or not. Considering how much Ipv4 is still a thing I’d assume the chances of this actually failing in the real world are low. Otherwise a bunch of Australians are gonna be unhappy they are stuck playing on North American servers.

I was unable to resolve the desktop issues with UnityEngine.Ping either. Firewall and administrator privileges didn’t appear to have any impact. Still fails with native Ipv6 addresses.

Hello.

Don’t know if still needed but you can try this (not tested on Android):

From the answer of "Ronald van Zoelen" on c# - Get IPv4 addresses from Dns.GetHostEntry() - Stack Overflow

public static string GetIPAddress(string hostname)
    {
        IPHostEntry host;
        host = Dns.GetHostEntry(hostname);

        foreach (IPAddress ip in host.AddressList)
        {
            if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            {
                //System.Diagnostics.Debug.WriteLine("LocalIPadress: " + ip);
                return ip.ToString();
            }
        }
        return string.Empty;
    }

You can use that to “extract” the IP address of your domain and then use it on “UnityEngine.Ping”

I used that (with some variations) due to some troubles with IPv6 and IPv4 in my windows app, here is my example: How to check internet connection in an app .(answer No.34)

Saludos.

1 Like

@TheLastVertex could you explain how you further process the PingReply?

//Works in Editor
//Errors on Android
System.Net.NetworkInformation.Ping oregon = new System.Net.NetworkInformation.Ping();
var oregonTask = oregon.SendPingAsync("www.google.com");
await oregonTask.ContinueWith((task) =>
{
    Debug.Log($"Ping RTT: {task.Result.RoundTripTime}");
});

I always get the a
System.Net.Sockets.SocketException (0x80004005): The operation completed successfully.

SocketException

System.Net.Sockets.Socket…ctor (System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType) (at :0)
System.Net.NetworkInformation.Ping.SendPrivileged (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) (at :0)
System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address, System.Int32 timeout, System.Byte[ ] buffer, System.Net.NetworkInformation.PingOptions options) (at :0)
System.Net.NetworkInformation.Ping+<>c__DisplayClass50_0.b__0 () (at :0)
System.Threading.Tasks.Task1[TResult].InnerInvoke () (at <9577ac7a62ef43179789031239ba8798>:0) System.Threading.Tasks.Task.Execute () (at <9577ac7a62ef43179789031239ba8798>:0) Rethrow as AggregateException: One or more errors occurred. System.Threading.Tasks.Task.ThrowIfExceptional (System.Boolean includeTaskCanceledExceptions) (at <9577ac7a62ef43179789031239ba8798>:0) System.Threading.Tasks.Task1[TResult].GetResultCore (System.Boolean waitCompletionNotification) (at <9577ac7a62ef43179789031239ba8798>:0)

This seems like a common error (here, there) for Unity, but unfortunalty no one could ever resolve it or post a valid solution.