我们正在更新套接字代码以处理您需要能够在仅IPv6环境中进行连接的新iOS要求。
我们目前正在使用.NET套接字和TcpClient。
我正在尝试建立一个IPv6和IPv4都可以工作的解决方案,但到目前为止还没有发生任何事情。
如果我使用:
TcpClient client = new TcpClient();
client.BeginConnect( "server.hostname.com", 8182, this._onConnect, client );
在IPv6环境中,我没有得到回复; <{1}}方法永远不会被触发。
如果我使用:
_onConnect
我得到TcpClient client = new TcpClient( AddressFamily.InterNetworkV6 );
client.BeginConnect( "server.hostname.com", 8182,this._onConnect, client);
:
SocketException
如果可以理解,这很烦人。如果我使用:
An address incompatible with the requested protocol was used (errorCode: 10047, socketErrorCode: AddressFamilyNotSupported, nativeErrorCode: 10047)
然后我可以连接,但是:
所以我想我可以从主机名获得支持的IP并尝试连接到一个接一个。
使用此代码:
TcpClient client = new TcpClient( AddressFamily.InterNetworkV6 );
client.BeginConnect( "xxxx:xxxx:xxxx::xxxx:xxxx", 8182,this._onConnect, client);
它只打印出IPv4 IP,这不是非常有用。
我在这里做错了什么?如何从字符串主机名获取IPv6 IP?或者有更好的方法来解决这个问题吗?
我有点假设这会在DNS级别自动解决,但我猜Unity中包含的Mono版本不够新。
由于
答案 0 :(得分:3)
@ Programmer的代码给出了主机名的IP地址,但我想澄清两件事。
1)代码:
TcpClient client = new TcpClient( AddressFamily.InterNetworkV6 );
client.BeginConnect( "server.hostname.com", 8182,this._onConnect, client);
DOES 工作,但仅适用于iOS。在编辑器和Android上,它提供了一个例外(从Unity 5.3.5f1开始)。这似乎是实现中的一个错误,所以我发送了一个错误报告。
2)尽管System.Net.Sockets.Socket.SupportsIPv6
被标记为过时且Unity建议您使用System.Net.Sockets.Socket.OSSupportsIPv6
,但OSSupportsIPv6
会在Android上引发异常
答案 1 :(得分:2)
看起来像是单声道,传递主机名来创建或连接到服务器将失败。使用直接IP始终有效。 Unity很长一段时间没有更新单声道插槽的东西。使用IP没有任何问题。
错过了苹果公司的截止日期。我的建议是先检查你的应用程序是否在iOS上运行,然后再使用IPv6。如果IPv6失败或返回null,则使用IPv4。
它只打印出IPv4 IP,这不是非常有用。
我在这里做错了什么?如何从字符串中获取IPv6 IP 主机名?或者有更好的方法来解决这个问题吗?
它打印出 IPv4 ,因为您不过滤了它。您必须手动检查每个循环中的ip是否为IPv6。
//IPv4
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
}
//IPv6
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
}
如果使用上述解决方案过滤掉 IPv6 ,那么这意味着您所在的网络不支持 IPv6 。当我这么说时,我的意思是你的ISP。如果您的ISP未提供 IPv6 ,则无法使用 IPv6 连接到其他公共服务器。您只能通过分配给您的ISP的 IPv4 连接到公共服务器。
要做到这一点,请访问here和here。它会告诉您是否有 IPv4 , IPv6 或两者都有。
以下代码是我用来检索本地公共IP的一般功能,包括版本4和6。
private string getIPAddress(string hostName, IPTYPE ipType, ADDRESSFAM Addfam)
{
//Return null if ADDRESSFAM is Ipv6 but Os does not support it
if (Addfam == ADDRESSFAM.IPv6 && !System.Net.Sockets.Socket.OSSupportsIPv6)
{
return null;
}
//////////////HANDLE LOCAL IP(IPv4 and IPv6)//////////////
if (ipType == IPTYPE.LOCAL_IP)
{
System.Net.IPHostEntry host;
string localIP = "";
host = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());
foreach (System.Net.IPAddress ip in host.AddressList)
{
//IPv4
if (Addfam == ADDRESSFAM.IPv4)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
//IPv6
else if (Addfam == ADDRESSFAM.IPv6)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
localIP = ip.ToString();
}
}
}
return localIP;
}
//////////////HANDLE PUBLIC IP(IPv4 and IPv6)//////////////
if (ipType == IPTYPE.PUBLIC_IP)
{
//Return if hostName String is null
if (string.IsNullOrEmpty(hostName))
{
return null;
}
System.Net.IPHostEntry host;
string localIP = "";
host = System.Net.Dns.GetHostEntry(hostName);
foreach (System.Net.IPAddress ip in host.AddressList)
{
//IPv4
if (Addfam == ADDRESSFAM.IPv4)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
//IPv6
else if (Addfam == ADDRESSFAM.IPv6)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
{
localIP = ip.ToString();
}
}
}
return localIP;
}
return null;
}
enum IPTYPE
{
LOCAL_IP, PUBLIC_IP
}
enum ADDRESSFAM
{
IPv4, IPv6
}
用法:
Debug.Log("Local IPv4: " + getIPAddress("", IPTYPE.LOCAL_IP, ADDRESSFAM.IPv4));
Debug.Log("Local IPv6: " + getIPAddress("", IPTYPE.LOCAL_IP, ADDRESSFAM.IPv6));
Debug.Log("Public IPv4: " + getIPAddress("google.com", IPTYPE.PUBLIC_IP, ADDRESSFAM.IPv4));
Debug.Log("Public IPv6: " + getIPAddress("google.com", IPTYPE.PUBLIC_IP, ADDRESSFAM.IPv6));