从主机名

时间:2016-06-06 16:16:54

标签: c# unity3d mono

我们正在更新套接字代码以处理您需要能够在仅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地址而不是主机名,这不是很好
  • 这将不再适用于IPv4环境

所以我想我可以从主机名获得支持的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版本不够新。

由于

2 个答案:

答案 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 连接到公共服务器。

要做到这一点,请访问herehere。它会告诉您是否有 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));