美文网首页iOS App上架那些事面试程序员
IOS上架之socket IPV6兼容问题

IOS上架之socket IPV6兼容问题

作者: 衣有油 | 来源:发表于2016-07-13 13:48 被阅读2494次

    前言

    6.1AppStore发布之后的应用要兼容ipv6。
    原因是美国ipv4的地址不足。
    其实在国内完全是相反的地位,连ipv6的服务器都不多,遍地是ipv4的地址。但是为了应付appstore的策略,势必是需要让app兼容的。
    我使用的是游戏引擎(cocos unity都用)所开发的项目,所以跨平台,但是android没有上架需求。所以是直接拿一套oc代码去做的IPV6兼容。

    原理

    我想很多人也会像我之前一样,不太了解什么是Ipv4和Ipv6,其实这只是个本地端口地址。
    哪里会用到这些地方呢? 应用有网络通信的地方,当然Http肯定不算,因为他只有post 和get方法,不需要用 Connect方法去和服务器做实时通信。所以一旦服务器有socket连接的时候,兼容Ipv6就势在必行了。

    socket连接

    既然提到了socket我觉得还是要提一下,不管是什么开发语言都会有这个连接库的底层封装的。举个例子:oc,c++,c#。或者是在网上随便一搜就是大把的socket i/o封装,归根结底,其实底层真正真正调用的方法无非就是几个,第一个 sockaddr_in,这是一个结构体,赋值这个结构体的sin_family ,sin_port ,sin_addr.s_addr三个值就够了。第二个是SOCKET 这个类对象赋值。
    为什么你的应用不兼容Ipv6,就是socket里面的connect方法下没做Ipv6判断以及没用ipv6自身的api。

    需要改.m 为.mm 加入#include<netdb.h> 头文件

    如何判断当前网络是否是ipv6

       +(NSString *) getIPWithHostName:(const NSString *)hostName
        {
        struct addrinfo * result;
         struct addrinfo * res;
        char ipv4[128];
        char ipv6[128];
        int error;
        BOOL IS_IPV6 = FALSE;
        bzero(&ipv4, sizeof(ipv4));
        bzero(&ipv4, sizeof(ipv6));
    
        error = getaddrinfo([hostName UTF8String], NULL, NULL, &result);
        if(error != 0) {
        NSLog(@"error in getaddrinfo:%d", error);
        return nil;
        }
         for(res = result; res!=NULL; res = res->ai_next) {
        char hostname[1025] = "";
        error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, 1025, NULL, 0, 0);
        if(error != 0) {
            NSLog(@"error in getnameifno: %s", gai_strerror(error));
            continue;
        }
        else {
            switch (res->ai_addr->sa_family) {
                case AF_INET:
                    memcpy(ipv4, hostname, 128);
                    break;
                case AF_INET6:
                    memcpy(ipv6, hostname, 128);
                    IS_IPV6 = TRUE;
                default:
                    break;
            }
            NSLog(@"hostname: %s ", hostname);
        }
        }
        freeaddrinfo(result);
        if(IS_IPV6 == TRUE) return [NSString stringWithUTF8String:ipv6];
        return [NSString stringWithUTF8String:ipv4];
        }
    

    这个函数既有了是否是ipv6的判断,也有了域名解析。
    至于域名解析的意思是,你需要把socket连接的ip地址改成域名。

    至于unity或者是cocos里面使用这代码,下个篇章我会详细讲oc与,c#,c++混编的内容,当然仅仅使用的话,我详细可以百度得到,不是一个非常困难的技术。

    测试

    • 你需要一个和mac连接的网线转接器,和根有网络的网线
    • 百度mac如何开启ipv6的网络
    • 注意:在点击共享的时候,是需要按住option键的
    • 真机测试:连上mac发出的wifi,测试网络是否通

    注意事项

    ipv6的兼容仅和客户端有关系。
    和服务端没半毛钱关系。请不要像我一样遇到这样的问题就甩锅给服务端了。
    深深的对不起我服务端大兄弟。

    相关文章

      网友评论

      • 聂飞缘:楼主你好,我的app上架的时候遇到了一个不兼容ipv6的问题,在ipv6网络下无法通过sockect连接服务器。底层是sockect通讯,但是是比较老的框架,不支持ipv6,那我应该怎么做,把原有的sockect代码修改一下就可以了吗?
        木马sun:楼主 我用的 第三方链接库 Alamofire, 是不是也要自己去改它源码呢? 因为也被拒了, 按理说是不是 Alamofire应该做好适配 ipv6的?
        聂飞缘:@衣有油 楼主,我的这个socket是用c语言写的,因为对这方面了解不是很深,是否可以把那个socket的代码给你,你帮我修改下,完事我给你点报酬可以嘛?公司这个项目急着上线。
        衣有油:@聂飞缘 是的,你只需要更改socket连接地方的代码,把ipv4的独有的api更改为 通过上述检测当前网络 去做ipv6的兼容,其实就是如此简单。
        http://blog.csdn.net/ozhonglou1234/article/details/51891734
        这是我另一篇博文,你可以通过看Connect 方法去看如何替换ipv4的独有API

      本文标题:IOS上架之socket IPV6兼容问题

      本文链接:https://www.haomeiwen.com/subject/ulmsjttx.html