iOS应用如何支持IPV6-b
一、IPV6-Only支持是啥?

NAT64-DNS64-ResolutionOfIPv4_2x.png

local_ipv6_dns64_nat64_network_2x.png
二、Apple如何审核支持IPV6-Only?
三、应用如何支持IPV6-Only?
1. Use High-Level Networking Frameworks;2. Don’t Use IP Address Literals;3. Check Source Code for IPv6 DNS64/NAT64 Incompatibilities;4. Use System APIs to Synthesize IPv6 Addresses;3.1 NSURLConnection是否支持IPV6?
using high-level networking APIs such as NSURLSession and the CFNetwork frameworks and you connect by name, you should not need to change anything for your app to work with IPv6 addresses
3.2 Cocoa的URL Loading System从iOS哪个版本开始支持IPV6?
3.3 Reachability是否需要修改支持IPV6?
1
2
3
|
在Pods:Reachability中 AF_INET Files:Reachability.m struct sockaddr_in Files:Reachability.h , Reachability.m |
(1)目前Github的开源库Reachability的最新版本是3.2,苹果也出了一个Support IPV6 的Reachability的官方样例,我们比较了一下源码,跟Github上的Reachability没有什么差异。
(2)我们通常都是通过一个0.0.0.0 (ZeroAddress)去开启网络状态监控,经过我们测试,在iOS9以上的系统上IPV4和IPV6网络环境均能够正常使用;但是在iOS8上IPV4和IPV6相互切换的时候无法监控到网络状态的变化,可能是因为苹果在iOS8上还并没有对IPV6进行相关支持相关。(但是这仍然满足苹果要求在最新系统版本上支持IPV6的网络)。
which reachability treats as a special token that causes it to actually
monitor the general routing status of the device, both IPv4 and IPv6.
1
2
3
4
5
6
7
|
+ (instancetype)reachabilityForInternetConnection { struct sockaddr_in zeroAddress; bzero(&zeroAddress, sizeof (zeroAddress)); zeroAddress.sin_len = sizeof (zeroAddress); zeroAddress.sin_family = AF_INET; return [ self reachabilityWithAddress: ( const struct sockaddr *) &zeroAddress]; } |
四、底层的socket API如何同时支持IPV4和IPV6?
- 本地网络环境的监测(本机IP+本地网关+本地DNS+域名解析);
- 通过TCP Connect监测到域名的连通性;
- 通过Ping 监测到目标主机的连通耗时;
- 通过traceRoute监测设备到目标主机中间每一个路由器节点的ICMP耗时;
4.1 IP地址从二进制到符号的转化
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//for IPV6 +( NSString *)formatIPV6Address:( struct in6_addr)ipv6Addr{ NSString *address = nil ; char dstStr[INET6_ADDRSTRLEN]; char srcStr[INET6_ADDRSTRLEN]; memcpy(srcStr, &ipv6Addr, sizeof ( struct in6_addr)); if (inet_ntop(AF_INET6, srcStr, dstStr, INET6_ADDRSTRLEN) != NULL ){ address = [ NSString stringWithUTF8String:dstStr]; } return address; } //for IPV4 +( NSString *)formatIPV4Address:( struct in_addr)ipv4Addr{ NSString *address = nil ; char dstStr[INET_ADDRSTRLEN]; char srcStr[INET_ADDRSTRLEN]; memcpy(srcStr, &ipv4Addr, sizeof ( struct in_addr)); if (inet_ntop(AF_INET, srcStr, dstStr, INET_ADDRSTRLEN) != NULL ){ address = [ NSString stringWithUTF8String:dstStr]; } return address; } |
4.2 本机IP获取支持IPV6
(1)在模拟器和真机上都会出现以FE80开头的IPV6单播地址影响我们判断,所以在这里进行特殊的处理(当第一次遇到不是单播地址的IP地址即为本机IP地址)。
(2)在IPV6环境下,真机测试的时候,第一个出现的是一个IPV4地址,所以在IPV4条件下第一次遇到单播地址不退出。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
+ ( NSString *)deviceIPAdress { while (temp_addr != NULL ) { NSLog ( @"ifa_name===%@" ,[ NSString stringWithUTF8String:temp_addr->ifa_name]); // Check if interface is en0 which is the wifi connection on the iPhone if ([[ NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString: @"en0" ] || [[ NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString: @"pdp_ip0" ]) { //如果是IPV4地址,直接转化 if (temp_addr->ifa_addr->sa_family == AF_INET){ // Get NSString from C String address = [ self formatIPV4Address:(( struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr]; } //如果是IPV6地址 else if (temp_addr->ifa_addr->sa_family == AF_INET6){ address = [ self formatIPV6Address:(( struct sockaddr_in6 *)temp_addr->ifa_addr)->sin6_addr]; if (address && ![address isEqualToString: @"" ] && ![address.uppercaseString hasPrefix: @"FE80" ]) break ; } } temp_addr = temp_addr->ifa_next; } } } |
4.3 设备网关地址获取获取支持IPV6
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/* net.route.0.inet.flags.gateway */ int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_FLAGS, RTF_GATEWAY}; if (sysctl(mib, sizeof (mib) / sizeof ( int ), buf, &l, 0, 0) < 0) { address = @"192.168.0.1" ; } .... //for IPV4 for (i = 0; i < RTAX_MAX; i++) { if (rt->rtm_addrs & (1 << i)) { sa_tab[i] = sa; sa = ( struct sockaddr *)(( char *)sa + ROUNDUP(sa->sa_len)); } else { sa_tab[i] = NULL ; } } //for IPV6 for (i = 0; i < RTAX_MAX; i++) { if (rt->rtm_addrs & (1 << i)) { sa_tab[i] = sa; sa = ( struct sockaddr_in6 *)(( char *)sa + sa->sin6_len); } else { sa_tab[i] = NULL ; } } |
4.4 设备DNS地址获取支持IPV6
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
+( NSArray *)outPutDNSServers{ res_state res = malloc( sizeof ( struct __res_state)); int result = res_ninit(res); NSMutableArray *servers = [[ NSMutableArray alloc] init]; if (result == 0) { union res_9_sockaddr_union *addr_union = malloc(res->nscount * sizeof ( union res_9_sockaddr_union)); res_getservers(res, addr_union, res->nscount); for ( int i = 0; i < res->nscount; i++) { if (addr_union[i].sin.sin_family == AF_INET) { char ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(addr_union[i].sin.sin_addr), ip, INET_ADDRSTRLEN); NSString *dnsIP = [ NSString stringWithUTF8String:ip]; [servers addObject:dnsIP]; NSLog ( @"IPv4 DNS IP: %@" , dnsIP); } else if (addr_union[i].sin6.sin6_family == AF_INET6) { char ip[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &(addr_union[i].sin6.sin6_addr), ip, INET6_ADDRSTRLEN); NSString *dnsIP = [ NSString stringWithUTF8String:ip]; [servers addObject:dnsIP]; NSLog ( @"IPv6 DNS IP: %@" , dnsIP); } else { NSLog ( @"Undefined family." ); } } } res_nclose(res); free(res); return [ NSArray arrayWithArray:servers]; } |
4.4 域名DNS地址获取支持IPV6
1
2
3
4
5
|
//ipv4 phot = gethostbyname(hostN); //ipv6 phot = gethostbyname2(hostN, AF_INET6); |
4.5 ping方案支持IPV6
https://developer.apple.com/library/mac/samplecode/SimplePing/Introduction/Intro.html
(1)返回的packet去掉了IPHeader部分,IPV6的header部分也不返回TTL(Time to Live)字段;
(2)IPV6的ICMP报文不进行checkSum的处理;
4.6 traceRoute方案支持IPV6
两个关键的地方需要注意:
(1)IPV6中去掉IP_TTL字段,改用跳数IPV6_UNICAST_HOPS来表示;
(2)sendto方法可以兼容支持IPV4和IPV6,但是需要最后一个参数,制定目标IP地址的大小;因为前一个参数只是指明了IP地址的开始地址。千万不要用统一的sizeof(struct sockaddr), 因为sockaddr_in 和 sockaddr都是16个字节,两者可以通用,但是sockaddr_in6的数据结构是28个字节,如果不显式指定,sendto方法就会一直返回-1,erroNo报22 Invalid argument的错误。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
//构造通用的IP地址结构stuck sockaddr NSString *ipAddr0 = [serverDNSs objectAtIndex:0]; //设置server主机的套接口地址 NSData *addrData = nil ; BOOL isIPV6 = NO ; if ([ipAddr0 rangeOfString: @":" ].location == NSNotFound ) { isIPV6 = NO ; struct sockaddr_in nativeAddr4; memset(&nativeAddr4, 0, sizeof (nativeAddr4)); nativeAddr4.sin_len = sizeof (nativeAddr4); nativeAddr4.sin_family = AF_INET; nativeAddr4.sin_port = htons(udpPort); inet_pton(AF_INET, ipAddr0.UTF8String, &nativeAddr4.sin_addr.s_addr); addrData = [ NSData dataWithBytes:&nativeAddr4 length: sizeof (nativeAddr4)]; } else { isIPV6 = YES ; struct sockaddr_in6 nativeAddr6; memset(&nativeAddr6, 0, sizeof (nativeAddr6)); nativeAddr6.sin6_len = sizeof (nativeAddr6); nativeAddr6.sin6_family = AF_INET6; nativeAddr6.sin6_port = htons(udpPort); inet_pton(AF_INET6, ipAddr0.UTF8String, &nativeAddr6.sin6_addr); addrData = [ NSData dataWithBytes:&nativeAddr6 length: sizeof (nativeAddr6)]; } struct sockaddr *destination; destination = ( struct sockaddr *)[addrData bytes]; //创建socket if ((recv_sock = socket(destination->sa_family, SOCK_DGRAM, isIPV6?IPPROTO_ICMPV6:IPPROTO_ICMP)) < 0) if ((send_sock = socket(destination->sa_family, SOCK_DGRAM, 0)) < 0) //设置sender 套接字的ttl if ((isIPV6? setsockopt(send_sock,IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl)): setsockopt(send_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl))) < 0) //发送成功返回值等于发送消息的长度 ssize_t sentLen = sendto(send_sock, cmsg, sizeof (cmsg), 0, ( struct sockaddr *)destination, isIPV6? sizeof ( struct sockaddr_in6): sizeof ( struct sockaddr_in)); |
iOS应用如何支持IPV6-b的更多相关文章
- iOS 支持 IPv6
苹果的规定:2016年6月1日提交到App Store必须支持IPv6-only网络. 官方文档:https://developer.apple.com/library/mac/documentati ...
- iOS应用支持IPV6,就那点事儿
原文连接 果然是苹果打个哈欠,iOS行业内就得起一次风暴呀.自从5月初Apple明文规定所有开发者在6月1号以后提交新版本需要支持IPV6-Only的网络,大家便开始热火朝天的研究如何支持IPV6 ...
- iOS应用支持IPV6
一.IPV6-Only支持是啥? 首先IPV6,是对IPV4地址空间的扩充.目前当我们用iOS设备连接上Wifi.4G.3G等网络时,设备被分配的地址均是IPV4地址,但是随着运营商和企业逐渐部署IP ...
- iOS 上线因iPv6被拒,查询服务器是否支持iPv6,mac设置iPv6网络,手机测试iPv6
一. iOS----如何检查域名是否支持ipv6 iOS----------如何检查域名是否支持ipv6 1.检查你所用到的库,像af 3.0以上什么的(不用改),其他的库自己去搜下是否支持ipv6吧 ...
- 提升iOS审核通过率之“IPv6兼容测试”
作者:jingle 腾讯系统测试工程师 商业转载请联系腾讯WeTest授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/285.html 一.背景 在 ...
- iOS----------如何检查域名是否支持ipv6
http://ipv6-test.com/validate.php 这个地址 也可以检测到! 1.检查你所用到的库,像af 3.0以上什么的(不用改),其他的库自己去搜下是否支持ipv6吧. 2. ...
- 配置阿里云ECS支持IPv6,解决苹果app审核失败问题
前几天iOS的App提交给苹果审核没通过,给出的原因是:该应用在 IPv6 的环境下无法使用.检查发现:阿里云优化过的系统没有启用IPv6协议,需要配置启用一下,但是只单独启用IPv6也是无法直接提供 ...
- iOS App 不支持http协议 App Transport Security has blocked a cleartext HTTP (http://)
目前iOS已经不支持http协议了,不过可以通过info.plist设置允许 App Transport Security has blocked a cleartext HTTP (http://) ...
- linux centos6.5支持ipv6
1.用ifconfig查看有没有inet6 addr,我的这个已经支持了,如果不支持请看第二步. 2.vim /etc/sysconfig/network 把这句改成:NETWORKING_IPV6= ...
随机推荐
- MVC-控制器向View传值的三种方法
1.提供视图模型对象 你能把一个对象作为View方法的参数传递给视图. public ViewResult Index() { DateTime date = DateTime.Now; return ...
- Robotium---环境搭建及入门示例
Robotium是一款基于控件的Android自动化测试框架 环境搭建(window): 安装JDK以及集成Android Sdk的eclipise. 入门: 1,下载Robotium Solo 5. ...
- [Redux] Using withRouter() to Inject the Params into Connected Components
We will learn how to use withRouter() to inject params provided by React Router into connected compo ...
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- BTrace使用总结
btracejvisualvmhotswap 一.背景 在生产环境中可能经常遇到各种问题,定位问题需要获取程序运行时的数据信息,如方法参数.返回值.全局变量.堆栈信息等.为了获取这些数 ...
- JAVA对象之生
https://yq.aliyun.com/users/1556056716932876?spm=5176.100239.blogrightarea55811.3.6cvyJd
- ZeroClipboard.swf
ZeroClipboard.config({ moviePath: "source/ZeroClipboard.swf", hove ...
- 可变字典 NSMutableDictionary
存到nsuesrDefault里面一个可变字典,然后用一个可变字典去接收. NSMutableDictionary *dic = [[NSUserDefaults standardUserDefaul ...
- RedHat7笔记
第一章 管理网络 查看网络信息 显示网卡状态# nmcli dev status列出所有连接# nmcli con show只列出可用连接# nmcli con show --active显示网卡配 ...
- Windows Server 2008中关闭事件跟踪程序的方法
Windows Server 2008跟Windows Server 2003一样,在关机的时候会弹出一个“关闭事件跟踪程序”窗口,当然微软这么做是处于安全的考虑啦,但是如果我们只是个人用用的话,那就 ...