IOS设备兼容Ipv5/ipv6访问Ipv4服务器

本文转载自:http://www.manew.com/thread-90569-1-1.html

这几天接到运营的一个苹果版 强制性需求,也就是 客户端 网络环境在 ipv4/ipv6 的情况下都能访问 公司外网服务器(ipv4),整理整理思绪。将自己的所测试成功的案例分享一下给有需要的朋友.
          
1.解决目标
   兼容移动设备(IOS系统)能够正常访问服务器(IPv4)。
2.解决思路
   2.1:了解苹果官方发布的兼容文档.
   2.2:了解unity3d访问IOS代码的流程.
   2.3:搭建测试环境
   2.4:测试兼容代码.
3.执行
   3.1:查看苹果官方发布的IPv6过度技术(https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW1)
   3.2:我们使用一个新建的unity3d工程进行我们的测试。U3D版本 必须是(4.7.2) 这个可以自行查看一下 u3d 官方的发行说明。
     3.2.1:打开新建的U3D调试工程,选择File菜单栏---->Build Settings----->IOS平台------->Ohter Settings----->Configuration---->Scriptiong Backend 选项(选择 IL2CPP) 以及 Architecture 选项(选择 Universal); 
         3.2.2:在苹果操作系统下新建一个 XCode(6.2以上(本人)) 工程--------->新建一个Object-C 文件------->新建的OC文件后缀 .m 更换为.mm文件 只为支持C/C++代码互编。接下来我们开始编写 苹果官方给出的 兼容代码。

        3.2.2.1:代码如下:

#define MakeStringCopy( _x_ ) ( _x_ != NULL && [_x_ isKindOfClass:[NSString class]] ) ? strdup( [_x_ UTF8String] ) : NULL
                    extern "C"{
                                const char* getIPv6(const char *mHost,const char *mPort)
                                {
                                        if( nil == mHost )
                                                return NULL;
                                        const char *newChar = "No";
                                        const char *cause = NULL;
                                        struct addrinfo* res0;
                                        struct addrinfo hints;
                                        struct addrinfo* res;
                                        int n, s;
                                        
                                        memset(&hints, 0, sizeof(hints));
                                        
                                        hints.ai_flags = AI_DEFAULT;
                                        hints.ai_family = PF_UNSPEC;
                                        hints.ai_socktype = SOCK_STREAM;
                                        //此处是IOS的关键函数
                                        if((n=getaddrinfo(mHost, "http", &hints, &res0))!=0)
                                        {
                                                printf("getaddrinfo error: %s\n",gai_strerror(n));
                                                return NULL;
                                        }
                                        
                                        struct sockaddr_in6* addr6;
                                        struct sockaddr_in* addr;
                                        NSString * NewStr = NULL;
                                        char ipbuf[32];
                                        s = -1;
                                        for(res = res0; res; res = res->ai_next)
                                        {
                                                if (res->ai_family == AF_INET6)
                                                {
                                                        addr6 =( struct sockaddr_in6*)res->ai_addr;
                                                        newChar = inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, sizeof(ipbuf));
                                                        NSString * TempA = [[NSString alloc] initWithCString:(const char*)newChar
                                                                                                                                                encoding:NSASCIIStringEncoding];
                                                        NSString * TempB = [NSString stringWithUTF8String:"&&ipv6"];
                                                        
                                                        NewStr = [TempA stringByAppendingString: TempB];
                                                        printf("%s\n", newChar);
                                                }
                                                else
                                                {
                                                        addr =( struct sockaddr_in*)res->ai_addr;
                                                        newChar = inet_ntop(AF_INET, &addr->sin_addr, ipbuf, sizeof(ipbuf));
                                                        NSString * TempA = [[NSString alloc] initWithCString:(const char*)newChar 
                                                                                                                                                encoding:NSASCIIStringEncoding];
                                                        NSString * TempB = [NSString stringWithUTF8String:"&&ipv4"];
                                                        
                                                        NewStr = [TempA stringByAppendingString: TempB];                        
                                                        printf("%s\n", newChar);
                                                }
                                                break;
                                        }
                                        
                                        
                                        freeaddrinfo(res0);
                                        
                                        printf("getaddrinfo OK");
                                        
                                        NSString * mIPaddr = NewStr;
                                        return MakeStringCopy(mIPaddr);
                                }
                        }
3.3:将编写好的OC(.mm)文件 复制到我们的Unity3d工程目录中的Assets----->Plugins--->ios(没有的话 新建一个文件夹命名为此 名字)文件夹下面。这样我们在 mac(苹果系统)下打包出来 会直接被带入到 XCode 工程 文件夹下面的 Libraries 文件目录下。
   3.4: 接下来 Unity3d客户端 这边调用 IOS 原生 代码:
     3.4.1:代码如下:
using System.Runtime.InteropServices; //引入此程序集可以调用IOS代码了。
                
                public class CompatibilityIP
                {
                        [DllImport("__Internal")]
                        private static extern string getIPv6(string host, string port);

                        private static string GetIPv6(string host, string port)
                        {
                #if UNITY_IPHONE && !UNITY_EDITOR
                                return getIPv6(host, port);
                #endif
                                return host + "&&ipv4";
                        }

                        public static void GetIpType(string serverIp,string serverPort,out  string newServerIp,out AddressFamily newServerAddressFamily)
                        {
                                newServerAddressFamily = AddressFamily.InterNetwork;
                                newServerIp = serverIp;
                                try
                                {
                                        string mIPv6 = GetIPv6(serverIp, serverPort);
                                        if (!string.IsNullOrEmpty(mIPv6))
                                        {
                                                string[] strTemp = Regex.Split(mIPv6, "&&");
                                                if (strTemp.Length >= 2)
                                                {
                                                        string type = strTemp[1];
                                                        if (type == "ipv6")
                                                        {
                                                                newServerIp = strTemp[0];
                                                                newServerAddressFamily = AddressFamily.InterNetworkV6;
                                                        }
                                                }
                                        }
                                }
                                catch (Exception e)
                                {
                                        Debug.LogError(e.Message);
                                }
                        }
                }
    3.5:修改Socket创建方式:
          3.5.1:代码如下:
string serverIp;
            AddressFamily ipType;
            CompatibilityIP.GetIpType("必须是域名IP(不能是数字IP)","端口号", out serverIp, out ipType);
                        Socket clientSocket = new Socket(ipType, SocketType.Stream, ProtocolType.Tcp);
                        IPAddress address = IPAddress.Parse(serverIp);
                        point = new IPEndPoint(address,端口号);
                        clientSocket.BeginConnect(point,异步连接回调函数, clientSocket);
5.结束
    以上事情都以准备完毕。剩下的就是使用 Unity3d客户端(4.7.2) 在 Mac(苹果系统) 下 Build 出来~。 Build 的完毕 打开 XCode 开发工具 进行 安装到IOS设备。安装完毕~在IOS设备上 任意切换 你的网络环境 进行测试。以上代码 亲测。已通过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值