2

How to get IP address on C# in program which developing for android device in Unity 2018.2+?

Seems like Network.player.ipAddress is deprecated right now, so I'm looking for a new way.

Programmer
  • 121,791
  • 22
  • 236
  • 328
Orkan
  • 71
  • 1
  • 2
  • 9
  • I searched it. But no new information about it on Stack. There is only discussions about old way of getting ip, which is depricated right now. – Orkan Aug 22 '18 at 22:41
  • ALERT - it does seem to be the case that you can now (late 2018?) simply call **nc.address**. – Fattie Oct 10 '18 at 18:08
  • LATER - this is ***FINALLY RESOLVED*** in the latest Unity. See long second answer. – Fattie Oct 10 '18 at 19:52

7 Answers7

15

The Network.player.ipAddress has been deprecated since it is based on the old obsolete Unity networking system.

If you are using Unity's new uNet Network System, you can use NetworkManager.networkAddress;

string IP = NetworkManager.singleton.networkAddress;

If you are using raw networking protocol and APIs like TCP/UDP, you have to use the NetworkInterface API to find the IP Address. I use IPManager which has been working for me on both desktop and mobile devices:

IPv4:

string ipv4 = IPManager.GetIP(ADDRESSFAM.IPv4);

IPv6:

string ipv6 = IPManager.GetIP(ADDRESSFAM.IPv6);

The IPManager class:

using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

public class IPManager
{
    public static string GetIP(ADDRESSFAM Addfam)
    {
        //Return null if ADDRESSFAM is Ipv6 but Os does not support it
        if (Addfam == ADDRESSFAM.IPv6 && !Socket.OSSupportsIPv6)
        {
            return null;
        }

        string output = "";

        foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
        {
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
            NetworkInterfaceType _type1 = NetworkInterfaceType.Wireless80211;
            NetworkInterfaceType _type2 = NetworkInterfaceType.Ethernet;

            if ((item.NetworkInterfaceType == _type1 || item.NetworkInterfaceType == _type2) && item.OperationalStatus == OperationalStatus.Up)
#endif 
            {
                foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
                {
                    //IPv4
                    if (Addfam == ADDRESSFAM.IPv4)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            output = ip.Address.ToString();
                        }
                    }

                    //IPv6
                    else if (Addfam == ADDRESSFAM.IPv6)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
                        {
                            output = ip.Address.ToString();
                        }
                    }
                }
            }
        }
        return output;
    }
}

public enum ADDRESSFAM
{
    IPv4, IPv6
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • How should I initialize NetworkManager? It gives me NullReferenceException. Was trying NetworkManager networkManager = NetworkManager.singleton; NetworkManager networkManager = new NetworkManager(); But there is new errors, exceptions dropping with this lines. – Orkan Aug 23 '18 at 12:10
  • You attach `NetworkManager` to a GameObject. If you haven't already attached `NetworkManager` to a GameObject then you are not using uNet and should use the second method in my answer. – Programmer Aug 23 '18 at 14:11
  • ALERT - it does seem to be the case that you can now (late 2018?) simply call **nc.address**. – Fattie Oct 10 '18 at 18:08
  • .. although only on the Server; you can't seem to get your "own" on a Client. – Fattie Oct 10 '18 at 18:24
  • @Fattie Hi, it was added in 2017.1 and that was even before my answer. The problem with using this is that is that you need to implement those functions you used to get that. You can't just directly access the ip address directly without those callback functions. That's the only issue I find with this. – Programmer Oct 10 '18 at 18:44
  • Which one. There are two examples. The `NetworkManager.singleton.networkAddress` or `GetIpv4` function? Sorry, but also, what do you mean by "type" – Programmer Oct 10 '18 at 19:07
  • OK, your excellent class `IPManager` does not work on a Mac sadly. (The reason it does not work is, `.NetworkInterfaceType` is f'ed up on a Mac, try spitting them out. Your code in `IPManager` involving your variable `_type` doesn't work on Mac.) – Fattie Oct 10 '18 at 19:26
  • @Programmer - ah, of course ! You can now actually use the weird `.connectionToClient` property and directly get it, ie on the server. (Whenever a "command" arrives from that client in question.) I will put in an answer. – Fattie Oct 10 '18 at 19:38
  • Just saw it and it looks grate. I think Unity update caused the issue in my code. Don't know which one but will update the code to something I currently use just in-case anyone want's to get IP without uNet – Programmer Oct 10 '18 at 20:03
  • @Programmer I wonder how you have Unity remove the lame ::ffff:192.168.0.120 "::ffff:" so annoying! : O – Fattie Oct 10 '18 at 20:37
  • Currently on my crappy computer because my Unity computer got liquid damage on the motherboard and can't do most things in Unity on it for days but taking a guess, it looks like Unity is mixing IPv6 with IPV4. – Programmer Oct 10 '18 at 20:52
  • @Fattie From my code you said it's not working, what happens when you replace `if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)` **with** `if ((item.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || item.NetworkInterfaceType == NetworkInterfaceType.Ethernet) && item.OperationalStatus == OperationalStatus.Up)`? If that doesn't fix your issue, can you log the `Debug.Log(item.NetworkInterfaceType)` and tell me the value? – Programmer Oct 10 '18 at 20:55
  • it just spewed 20 of the same pointless text description (I think it was "interface") - you know, unfortunately I worked onwards with the code and it's gone now! If I get a minute I'll rewind and put the info here ......... apple idiots – Fattie Oct 11 '18 at 11:59
  • There is a bug with the `NetworkInterface.NetworkInterfaceType` property and I have verified this not on MacOS but on Android. That's why there is different function for mobile devices in my original answer. I have modified the answer to only allow the use of the `NetworkInterface.NetworkInterfaceType` property **only** on Windows since that's the only platform it works on so far. If what you're using from your answer is working for you fine then go with it, if it's not use the updated code in my answer. I also added IPv6 support especially since that's now required on iOS and Mac. – Programmer Oct 11 '18 at 12:57
  • @Programmer re the bug with NetworkInterfaceType, can you be specific ? I'm seeing that field reliably return "Ethernet" for "en*" interfaces on MacOS (10.13) and iOS (12.1). I haven't had a chance to test Android yet tho. I do see that "OperationalStatus" is "Unknown" on MacOS and iOS tho. So modifying your code a bit to include the checks on Type but not the check on OperationalStatus works well for me. I'll post the result as a new answer – orion elenzil Jan 25 '19 at 18:36
2
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

public class TestLocationService : MonoBehaviour
{
    public Text hintText;

    private void Start()
    {
        GetLocalIPAddress();
    }
    public string GetLocalIPAddress()
    {
        var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                hintText.text = ip.ToString();
                return ip.ToString();
            }
        }
        throw new System.Exception("No network adapters with an IPv4 address in the system!");
    }

}
1

FINALLY resolved by Unity (from about version 2018.2)

Inside any [Command] arriving on the server,

the IP of the client, which, sent the [Command] is

        connectionToClient.address

Phew.


You will in fact have your own NetworkBehaviour derived class, you must do this. (It is very often called "Comms"):

public partial class Comms : NetworkBehaviour {

That class must override both the server/client startoffs, so that each Comms "knows what it is".

public override void OnStartServer() {
    .. this "Comms" does know it IS the server ..
}

public override void OnStartLocalPlayer() {
    .. this "Comms" does know it IS one of the clients ..
}

On any actual project, since Unity doesn't do it, the clients must identify themselves to the server. You have to entirely handle that in Unity networking, from scratch.

(Note. that process is explained in the long blog here

https://forum.unity.com/threads/networkmanager-error-server-client-disconnect-error-1.439245/#post-3754939 )

So this would be the first thing you (must) do in OnStartLocalPlayer

public override void OnStartLocalPlayer() {
    
    Grid.commsLocalPlayer = this;

    StandardCodeYouMustHave_IdentifySelfToServer();
    
    // hundreds of other things to do..
    // hundreds of other things to do..
}

That "command pair" inside comms would look like this:

You must do this in all networking projects (or you will have no clue which client is which):

public void StandardCodeYouMustHave_IdentifySelfToServer() {
    
    string identityString = "quarterback" "linebacker" "johnny smith"
        .. or whatever this device is ..

    CmdIdentifySelfToServer( identityString );

    // hundreds more lines of your code
    // hundreds more lines of your code
}

[Command]
void CmdIdentifySelfToServer(string connectingClientIdString) {
    
    .. you now know this connection is a "connectingClientIdString"
    .. and Unity gives you the connection: in the property: connectionToClient
    .. you must record this in a hash, database, or whatever you like

    MakeANote( connectingClientIdString , connectionToClient )

    // hundreds more lines of your code
    // hundreds more lines of your code
}

The good news is Unity have added the connectionToClient property, that is to say on the server, inside a [Command].

And then, you can indeed use the new .address property on that.

YOU CAN FINALLY GET THE IP OF THAT CLIENT!

public void StandardCodeYouMustHave_IdentifySelfToServer() {
    CmdIdentifySelfToServer( identityString );
}

[Command]
void CmdIdentifySelfToServer(string connectingClientIdString) {
    MakeANote( connectingClientIdString , connectionToClient )
    string THEDAMNEDIP = connectionToClient.address;
}

It's that "simple", the ip of the client, which just connected, is "THEDAMNEDIP".

Phew.

Only took Unity 5? years.

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
0

For 2018...

However, SEE THE NEWER ANSWER BELOW.

It does seem to be the case that you can now call - on the server, in NetworkManager - simply NetworkConnection#address and it will give it to you.

Recall that you must write your own NetworkManager, it does not work out of the box. Explained here if yer new to unity networking:

https://forum.unity.com/threads/networkmanager-error-server-client-disconnect-error-1.439245/#post-3754939

public class OurNetworkManager : NetworkManager {

    //
    // server .............
    //

    public override void OnServerConnect(NetworkConnection nc) {

        // it means "here on the server" one of the clients has connected
        base.OnServerConnect(nc);

        Log("a client connected " + nc.connectionId + " " + nc.hostId);
        Log("address? " + nc.address);
    }

    public override void OnServerDisconnect(NetworkConnection nc) { .. etc

.

However note that

1) this only gives it to you on the server,

2) and only at "NetworkManager" which (of course!) is not actually when you identify each connecting client

Note the even newer answer - Unity finally resolved this.

Fattie
  • 27,874
  • 70
  • 431
  • 719
0

this is a minor modification to the excellent answer already provided by @Programmer. the motivation here is to improve functionality on MacOS and iOS. i haven't looked at android yet. i've also only tested IPV4.

what's different from @Programmer's original:

  1. for MacOS and iOS, include the filter on Interface Type
  2. .. but exclude the check on OperationalStatus
  3. move the enum into the class
  4. mark the class as static
  5. refactor so there's one method which returns all the matching IPs,
    and another to simply return the last one, which matches the logic of the original version.
  6. also included a diagnostic option for the list of IPs to include some details such as the "Description" of the interface (eg en0, en1). This option should obviously not be used if all you want is the IP address itself.
public static class IPManager
{
    public enum ADDRESSFAM
    {
        IPv4, IPv6
    }

    public static string GetIP(ADDRESSFAM Addfam)
    {
      string ret = "";
      List<string> IPs = GetAllIPs(Addfam, false);
      if (IPs.Count > 0) {
        ret = IPs[IPs.Count - 1];
      }
      return ret;
    }

    public static List<string> GetAllIPs(ADDRESSFAM Addfam, bool includeDetails)
    {
        //Return null if ADDRESSFAM is Ipv6 but Os does not support it
        if (Addfam == ADDRESSFAM.IPv6 && !Socket.OSSupportsIPv6)
        {
            return null;
        }

        List<string> output = new List<string>();

        foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
        {

#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IOS
            NetworkInterfaceType _type1 = NetworkInterfaceType.Wireless80211;
            NetworkInterfaceType _type2 = NetworkInterfaceType.Ethernet;

            bool isCandidate = (item.NetworkInterfaceType == _type1 || item.NetworkInterfaceType == _type2);

#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
            // as of MacOS (10.13) and iOS (12.1), OperationalStatus seems to be always "Unknown".
            isCandidate = isCandidate && item.OperationalStatus == OperationalStatus.Up;
#endif

            if (isCandidate)
#endif 
            {
                foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
                {
                    //IPv4
                    if (Addfam == ADDRESSFAM.IPv4)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            string s = ip.Address.ToString();
                            if (includeDetails) {
                                s += "  " + item.Description.PadLeft(6) + item.NetworkInterfaceType.ToString().PadLeft(10);
                            }
                            output.Add(s);
                        }
                    }

                    //IPv6
                    else if (Addfam == ADDRESSFAM.IPv6)
                    {
                        if (ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
                        {
                            output.Add(ip.Address.ToString());
                        }
                    }
                }
            }
        }
        return output;
    }
}
orion elenzil
  • 4,484
  • 3
  • 37
  • 49
0
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System;
using UnityEngine.Networking;
using Newtonsoft.Json;

public class geoplugin
{
    //Assume E.g. before each comment
    public string geoplugin_request; //THIS IS THE IP ADDRESS
    public int geoplugin_status; //200
    public string geoplugin_delay; //"1ms"
    public string geoplugin_credit;
    public string geoplugin_city; //E.g Toronto. 
    public string geoplugin_region; //E.g. Ontario
    public string geoplugin_regionCode; //E.g. ON
    public string geoplugin_regionName; //Also Ontario
    public string geoplugin_areaCode; //idk
    public string geoplugin_dmaCode; //idk
    public string geoplugin_countryCode; //E.g. CA (that's Canada)
    public string geoplugin_countryName; //E.g. Canada
    public int geoplugin_inEU; //0 if not in EU
    public bool geoplugin_euVATrate; //false
    public string geoplugin_continentCode; //E.g. NA
    public string geoplugin_continentName; //North America
    public string geoplugin_latitude; 
    public string geoplugin_longitude; 
    public string geoplugin_locationAccuracyRadius; //"1"
    public string geoplugin_timezone; //"America\/Toronto",
    public string geoplugin_currencyCode; //"CAD",
    public string geoplugin_currencySymbol; //"$",
    public string geoplugin_currencySymbol_UTF8; //$",
    public float geoplugin_currencyConverter;
}

public class GetMyIP : MonoBehaviour 
{
    geoplugin geoInfo;
    string ip;


    public void GetIP()
    {
        StartCoroutine(GetRequest("http://www.geoplugin.net/json.gp", (UnityWebRequest req) =>
        {
            if (req.isNetworkError || req.isHttpError)
            {
                Debug.Log($"{req.error}: {req.downloadHandler.text}");
            }
            else
            {
                geoplugin geopluginData = JsonConvert.DeserializeObject<geoplugin>(req.downloadHandler.text);

                ip = geopluginData.geoplugin_request;
                geoInfo = geopluginData;
                Debug.Log(ip);

                //AT THIS POINT IN THE CODE YOU CAN DO WHATEVER YOU WANT WITH THE IP ADDRESS
            }
        }));
    }

    IEnumerator GetRequest(string endpoint, Action<UnityWebRequest> callback)
    {
        using (UnityWebRequest request = UnityWebRequest.Get(endpoint))
        {
            // Send the request and wait for a response
            yield return request.SendWebRequest();

            callback(request);
        }
    }
}

This should give you the ip address stored in the string ip, which you can use for whatever you want. It's also possible that this will get you a lot of information that you needed the ip address for in the first place.

That was my experience anyways. I was trying to create an in game weather system that matched the real world weather, and I wanted the ip address to then find the location but this site provides both, removing the need to get the ip address first.

This is the tutorial I followed to figure out this code: https://theslidefactory.com/using-unitywebrequest-to-download-resources-in-unity/

You'll also need to import this for the code to work: https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347

If you just want the ip address and nothing else, then this is not the best solution. However, most of the time, you want to do something with the ip address, like get location, and this provides a lot of that stuff that you might be trying to get.

Ahsen Khan
  • 171
  • 1
  • 5
0

https://stackoverflow.com/a/67450052/18192881

In regards to the geofilter data post, according to their Terms: "RESTRICTIONS. General. You may not, nor may you permit others to:

ix: use the Services for the purpose of identifying or locating a specific individual or household."

So I wouldn't rely on them for this, as it is 'illegal?' or at least against thier policy.