简体   繁体   中英

How to get IP address of device in Unity 2018+?

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.

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
}

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.

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.

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

}
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM