如何在Unity 2018.2+中为Android设备开发的程序中获取C#的IP地址?
似乎Network.player.ipAddress
现在已不推荐使用,所以我正在寻找一种新方法。
答案 0 :(得分:6)
Network.player.ipAddress
已基于旧的过时的Unity网络系统而被弃用。
如果您正在使用Unity的新uNet网络系统,则可以使用NetworkManager.networkAddress
;
string IP = NetworkManager.singleton.networkAddress;
如果您使用的是原始网络协议和TCP / UDP等API,则必须使用NetworkInterface
API来查找IP地址。我使用IPManager
在台式机和移动设备上一直在为我工作:
IPv4 :
string ipv4 = IPManager.GetIP(ADDRESSFAM.IPv4);
IPv6 :
string ipv6 = IPManager.GetIP(ADDRESSFAM.IPv6);
IPManager
类:
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
}
答案 1 :(得分:2)
在到达服务器的任何[Command]
内,
发送[Command]
的客户端的IP是
connectionToClient.address
Ph。
实际上,您将拥有自己的NetworkBehaviour
派生类,您必须这样做。 (通常称为“通讯”):
public partial class Comms : NetworkBehaviour {
该类必须覆盖服务器/客户端的两个起点,以便每个Comms“知道它是什么”。
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 ..
}
在任何实际项目中,由于Unity不执行此操作,因此客户端必须向服务器标识自己。您必须从头开始在Unity网络中完全解决这个问题。
(注意。有关此过程的详细说明,请参见此处
这将是您(必须)在OnStartLocalPlayer
public override void OnStartLocalPlayer() {
Grid.commsLocalPlayer = this;
StandardCodeYouMustHave_IdentifySelfToServer();
// hundreds of other things to do..
// hundreds of other things to do..
}
通讯中的“命令对”看起来像这样:
您必须在所有联网项目中执行此操作(否则您将不知道哪个客户端是哪个客户端):
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
}
好消息是Unity在connectionToClient
内的服务器上添加了[Command]
属性。
然后,您确实可以在其上使用新的.address
属性。
public void StandardCodeYouMustHave_IdentifySelfToServer() {
CmdIdentifySelfToServer( identityString );
}
[Command]
void CmdIdentifySelfToServer(string connectingClientIdString) {
MakeANote( connectingClientIdString , connectionToClient )
string THEDAMNEDIP = connectionToClient.address;
}
就是刚刚连接的客户端的IP“简单”就是“ THEDAMNEDIP”。
Ph。
仅使用Unity 5?年。
答案 2 :(得分:1)
对于2018年...
现在看来,您现在可以调用-在服务器上的NetworkManager中了-只需NetworkConnection#address
,它就会给您。
回想一下,您必须编写自己的NetworkManager,但它开箱即用。如果您不熟悉统一网络,请在此处说明:
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
。
1)仅将它提供给您在服务器上
2),并且仅在“ NetworkManager”中(当然!)是 ,当您确定每个连接的客户端时实际上不是
请注意更新的答案-Unity终于解决了这个问题。
答案 3 :(得分:0)
这是对excellent answer already provided by @Programmer的较小修改。这样做的动机是为了改善MacOS和iOS上的功能。我还没有看过android。我也只测试了IPV4。
与@Programmer的原始内容有何不同:
en0
,en1
)。如果您只需要IP地址本身,则显然不应使用此选项。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;
}
}
答案 4 :(得分:0)
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!");
}
}
答案 5 :(得分: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);
}
}
}
这应该会为您提供存储在字符串 ip
中的 IP 地址,您可以随意使用它。也有可能这会为您提供很多信息,而您首先需要获取 IP 地址。
这就是我的经历。我试图创建一个与现实世界天气相匹配的游戏天气系统,我想要 IP 地址然后找到位置,但该站点提供了两者,无需先获取 IP 地址。
这是我用来找出这段代码的教程:https://theslidefactory.com/using-unitywebrequest-to-download-resources-in-unity/
您还需要导入此代码才能工作:https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347
如果你只想要IP地址而不是别的,那么这不是最好的解决方案。但是,大多数情况下,您想对 IP 地址执行某些操作,例如获取位置,这提供了您可能想要获取的许多内容。