Search Unity

Question Ping a domain name or Ipv6 address

Discussion in 'Multiplayer' started by TheLastVertex, Aug 16, 2020.

  1. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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.

    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?

    Code (CSharp):
    1.  
    2. //Works in Editor
    3. //Errors on Android
    4. System.Net.NetworkInformation.Ping oregon = new System.Net.NetworkInformation.Ping();
    5. var oregonTask = oregon.SendPingAsync("gamelift.us-west-2.amazonaws.com");
    6. await oregonTask.ContinueWith((task) =>
    7. {
    8.  
    9. });
    10.  
    11. //Works in Editor
    12. //Errors on Android
    13. System.Net.NetworkInformation.Ping oregon = new System.Net.NetworkInformation.Ping();
    14. var test = oregon.Send("gamelift.us-west-2.amazonaws.com");
    15.  
    16. while(test.Status != IPStatus.Success)
    17. {
    18.    yield return null;
    19. }
    20.  
    21.  
     
    ryan_santiago_dl likes this.
  2. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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.

    Code (CSharp):
    1. System.Net.IPHostEntry myHost = System.Net.Dns.GetHostEntry("gamelift.us-west-2.amazonaws.com");
    2. string myIp = myHost.AddressList[0].ToString();
    3.  
    4. UnityEngine.Ping pingReply = new UnityEngine.Ping(myIp);
    5. while(pingReply.isDone == false)
    6. {
    7.     yield return null;
    8. }
    9.  
    10. 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.
     
    Last edited: Aug 17, 2020
  3. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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.

    Code (CSharp):
    1. //Get the IP from domain name
    2. IPHostEntry myHost = Dns.GetHostEntry("gamelift.us-west-2.amazonaws.com");
    3. string myIp = myHost.AddressList[0].ToString();
    4.  
    5. if (myHost.AddressList.Length >= 1 && !String.IsNullOrEmpty(myIp))
    6. {
    7.     //Map the ipv4 address to ipv6
    8.     IPAddress newAddress = IPAddress.Parse(myIp);
    9.     if (newAddress.IsIPv4MappedToIPv6 == false)
    10.     {
    11.         IPAddress myipv6Address = newAddress.MapToIPv6();
    12.         myIp = myipv6Address.ToString();
    13.     }
    14.  
    15.     //Ping the Ip
    16.     UnityEngine.Ping pingReply = new UnityEngine.Ping(myIp);
    17.     while (pingReply.isDone == false)
    18.     {
    19.         yield return null;
    20.         Debug.Log("GetAwsRegionPingData...");
    21.     }
    22.  
    23.     Debug.LogError("GetAwsRegionPingData - Oregon: " + pingReply.time);
    24. }
     
    Last edited: Aug 17, 2020
  4. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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.

    https://issuetracker.unity3d.com/issues/unityengine-dot-ping-does-not-work-with-ipv6-addresses

    Code (CSharp):
    1. System.Net.IPHostEntry googleHostEntry = System.Net.Dns.GetHostEntry("google.com");
    2. string googleIP = googleHostEntry.AddressList[0].ToString();
    3. Debug.LogError("Google IP: " + googleIP);
    4.  
    5. UnityEngine.Ping pingReply = new UnityEngine.Ping(googleIP);
    6. while (pingReply.isDone == false)
    7. {
    8.     yield return null;
    9.     Debug.Log("GetAwsRegionPingData...");
    10. }
    11.  
    12. Debug.LogError("GetAwsRegionPingData - Google - Ip: " + pingReply.ip + "  RTT: " + pingReply.time);
     
    Last edited: Aug 17, 2020
  5. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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.

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

    Code (CSharp):
    1. IPHostEntry myHost = Dns.GetHostEntry("google.com");
    2.  
    3. System.Net.NetworkInformation.Ping myPing = new System.Net.NetworkInformation.Ping();
    4. var pingReply = myPing.Send(myHost.AddressList[0]);
    5. if (pingReply.Status == IPStatus.Success)
    6. {
    7.     Debug.LogError("GetAWSRegionPingData " + pingReply.RoundtripTime);
    8. }
    9. else
    10. {
    11.     Debug.LogError("GetAWSRegionPingData " + pingReply.Status);
    12. }
    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.
     
  6. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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...
    Code (CSharp):
    1. IPHostEntry myHost = Dns.GetHostEntry("google.com");
    2. string myIp = myHost.AddressList[0].ToString();
    3. UnityEngine.Ping myPing = new UnityEngine.Ping(myIp);
    4.      
    5. while(myPing.isDone == false)
    6. {
    7.     Debug.Log("GetAWSRegionPingData waiting..." + myIp);
    8.     yield return null;
    9. }
    10.  
    11. Debug.LogError("GetAWSRegionPingData " + myIp +" RTT:" + myPing.time);
     
  7. TheLastVertex

    TheLastVertex

    Joined:
    Sep 30, 2015
    Posts:
    126
    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.
     
  8. marck_ozz

    marck_ozz

    Joined:
    Nov 30, 2018
    Posts:
    107
    Hello.

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

    From the answer of "Ronald van Zoelen" on https://stackoverflow.com/questions/1059526/get-ipv4-addresses-from-dns-gethostentry

    Code (CSharp):
    1. public static string GetIPAddress(string hostname)
    2.     {
    3.         IPHostEntry host;
    4.         host = Dns.GetHostEntry(hostname);
    5.  
    6.         foreach (IPAddress ip in host.AddressList)
    7.         {
    8.             if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
    9.             {
    10.                 //System.Diagnostics.Debug.WriteLine("LocalIPadress: " + ip);
    11.                 return ip.ToString();
    12.             }
    13.         }
    14.         return string.Empty;
    15.     }
    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: https://forum.unity.com/threads/how-to-check-internet-connection-in-an-app.384541/#post-6667402 .(answer No.34)

    Saludos.
     
    Noxury likes this.
  9. Noxury

    Noxury

    Joined:
    Mar 8, 2015
    Posts:
    22
    @TheLastVertex could you explain how you further process the PingReply?
    Code (CSharp):
    1. //Works in Editor
    2. //Errors on Android
    3. System.Net.NetworkInformation.Ping oregon = new System.Net.NetworkInformation.Ping();
    4. var oregonTask = oregon.SendPingAsync("www.google.com");
    5. await oregonTask.ContinueWith((task) =>
    6. {
    7.     Debug.Log($"Ping RTT: {task.Result.RoundTripTime}");
    8. });
    I always get the a
    System.Net.Sockets.SocketException (0x80004005): The operation completed successfully.

    System.Net.Sockets.Socket..ctor (System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType) (at <ef151b6abb5d474cb2c1cb8906a8b5a4>:0)
    System.Net.NetworkInformation.Ping.SendPrivileged (System.Net.IPAddress address, System.Int32 timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) (at <ef151b6abb5d474cb2c1cb8906a8b5a4>:0)
    System.Net.NetworkInformation.Ping.Send (System.Net.IPAddress address, System.Int32 timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) (at <ef151b6abb5d474cb2c1cb8906a8b5a4>:0)
    System.Net.NetworkInformation.Ping+<>c__DisplayClass50_0.<SendPingAsync>b__0 () (at <ef151b6abb5d474cb2c1cb8906a8b5a4>:0)
    System.Threading.Tasks.Task`1[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.Task`1[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.
     
    Last edited: Mar 10, 2022