iOS 支持IPv6-Only网络资料整理

作者: HK_Hank | 来源:发表于2016-07-31 17:46 被阅读1670次

    导语:

    自从5月初Apple明文规定所有开发者在6月1号以后提交新版本需要支持IPV6-Only的网络。自从苹果实施以来,也遇到了各种各样的问题,现此把知道的资料整理一下

    首先,说明一下什么是IPv6

    IPv6是Internet Protocol Version 6的缩写,其中Internet Protocol译为“互联网协议”。IPv6是IETF(互联网工程任务组,Internet Engineering Task Force)设计的用于替代现行版本IP协议(IPv4)的下一代IP协议,号称可以为全世界的每一粒沙子编上一个网址[1]。

    为什么用IPv6?

    由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍。
    与IPv4相比,IPv6具有更大的地址空间。IPv4中规定IP地址长度为32,最大地址个数为232;而IPv6中IP地址的长度为128,即最大地址个数为2128。与32位地址空间相比,其地址空间增加了2128-232个。
    其他优势,请大家自行Google。

    IPv6地址是什么样的?

    IPv6地址格式为X:X:X:X:X:X:X:X,其中每个X表示地址中的16b,以十六进制表示,例如:ABCD:EF01:2345:6789:ABCD:EF01:2345:6789

    苹果指的IPv6-Only网络是什么?

    IPv6 DNS64/NAT64网络即是所谓的IPV6-Only网络,该网络可以通过转换的方式来继续访问IPv4地址。

    IPv6 DNS64/NAT64网络是什么?

    可以通过以下流程图和时序图来了解


    NAT流程
    IPv6 DNS64/NAT64网络下IPv6地址与IPv4地址交互的时序图
    其中

    DNS(Domain Name System,域名系统),通过DNS服务器,解析域名为IP地址
    NAT(Network Address Translation,网络地址转换),内网IP地址到外网IP地址的转换

    我现在是IPv4网络环境,我该怎么测试IPv6网络呢?

    苹果提供了一个搭建虚拟IPv6 DNS64/NAT64网络的方法,要求Mac设备在Mac OS 10.11以上系统,通过有线网开一个IPv6-Only网络的热点,原理图如下:


    Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png

    出现以下图片,即热点开成功了


    Paste_Image.png

    Apple如何审核支持IPV6-Only?

    经过查阅相关资料和上传的版本来看,苹果审核的时候使用最新的系统(目前是IOS9.3.2)来测试IPv6-Only网络的,应该是在该网络下可以正常使用即可。并不会扫描应用内IPv4专有的底层API。

    Note: In iOS 9 and OS X 10.11 and later, NSURLSession and CFNetwork automatically synthesize IPv6 addresses from IPv4 literals locally on devices operating on DNS64/NAT64 networks. However, you should still work to rid your code of IP address literals.

    对于使用了写死IPv4地址来交互的朋友。苹果提到,在iOS9以上的系统,苹果自己会做IPv4转IPv6地址的转换,所以如果应用中写死的IPv4地址,并且是使用NSURLSession and CFNetwork(测试发现NSURLConnection也是可以的)来做网络请求,则在IOS9以上系统,还是可以在IPv6-Only网络正常运行的,所以是可以通过审核的之后可能还是有风险,建议还是换成域名)。

    应用如何支持IPV6-Only?

    • 使用AFetworking做网络交互的朋友,需要使用最新版本替换AFNetworking中的Reachability类(看源码发现,也只是针对iOS9以上的系统做了特殊处理)
    • ASIHttpRequest虽然使用的是CFNetwork,但是在网上看到有人反应,IPv6网络上不能正常运行,所以。。。还是换AFNetworking吧,ASI早就没人维护了
    • 对于底层的socket API,这一块,主要是在IPv6-Only网络下,需要将IPv4地址转换为IPv6地址,可以参考笔者后面提供的代码,还要要注意的是,可能有的服务端那边会通过请求头中的Host来校验是IPv4还是IPv6环境(不处理的话,默认Host中会是IPv6地址),所以Host这个地方需要注意一下(服务端没有配IPv6地址的换,可能会有问题),根据具体场景来处理
    • 对于播放这一块,如果使用的是系统的播放器,走的是HLS,而且使用的写死IPv4地址。对于清流的片源,经过我们的测试,只要把开始的播放URL(重定向之前的URL)中将IPv4地址转换为IPv6地址即可。

    iOS中将IPv4地址转换为IPv6地址

    在iOS 9.2版本系统后,通过getaddrinfo转换ipv4得到ipv6地址,该方法只能在iOS9.2以后才有效。
    OC代码

    #include <sys/socket.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <err.h>
    
    #define CopyString(temp) (temp != NULL)? strdup(temp):NULL
    - (NSString *)getIPAddress:(NSString *)ipAddress {
        if (!ipAddress) {
            return @"";
        }
    
        struct addrinfo hints, *res, *res0;
        int error;
    
        const char *ipv4_str = [ipAddress UTF8String];
        
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = PF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_DEFAULT;
        error = getaddrinfo(ipv4_str, "http", &hints, &res0);
        if (error) {
            errx(1, "%s", gai_strerror(error));
            return @"";
        }
        
        struct sockaddr_in6* addr6;
        struct sockaddr_in * addr;
        const char* pszTemp;
        
        for (res = res0; res; res = res->ai_next) {
            char buf[32];
            if(res->ai_family == AF_INET6) {
                addr6 = (struct sockaddr_in6*)res->ai_addr;
                pszTemp = inet_ntop(AF_INET6, &addr6->sin6_addr, buf, sizeof(buf));
            } else {
                 addr = (struct sockaddr_in*)res->ai_addr;
                 pszTemp = inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf));
            }
    
            break;
        }
        
        freeaddrinfo(res0);
        printf("getaddrinfo ok %s\n", pszTemp);
        return [NSString stringWithFormat:@"%s",CopyString(pszTemp)];
    }
    

    C++代码可以参照:
    iOS 解决ipv6问题

    相关文章

      网友评论

      • 1ed4d2c1f936:你好,我的设置那块并没有出现勾选ipv6的选项。那这要怎么操作啊?
        1ed4d2c1f936:@HK_Hank 我设置成功了,但是并没有出现那个图片
        1ed4d2c1f936:@HK_Hank 我的键盘不是苹果的,然后试了下是alt键
        HK_Hank:要求Mac设备在Mac OS 10.11以上系统,进入设置页面,按住Option键点击分享。
      • 聂飞缘:楼主,我的app通讯是使用sockect通讯的,要怎么改呢
        HK_Hank:@聂飞缘 第三方库应该能支持IPv6的吧,主要是要判断一下当前网络环境是IPv6还是IPv4,可以使用http://www.cnblogs.com/HemJohn/p/5590483.html中博客里面C++的方法获取IP地址后,判断是IPv4还是IPv6环境
        聂飞缘:@HK_Hank 第三方库
        HK_Hank:@聂飞缘 你这边socked通讯,是使用第三方开源的库呢,还是直接使用的系统底层的socket通讯的?

      本文标题:iOS 支持IPv6-Only网络资料整理

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