日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS应用支持IPV6,就那点事儿

發(fā)布時間:2023/12/31 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS应用支持IPV6,就那点事儿 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

果然是蘋果打個哈欠,iOS行業(yè)內就得起一次風暴呀。自從5月初Apple明文規(guī)定所有開發(fā)者在6月1號以后提交新版本需要支持IPV6-Only的網絡,大家便開始熱火朝天的研究如何支持IPV6,以及應用中哪些模塊目前不支持IPV6。

為了更好的交流,特建了一個IPV6交流群(群號:574410254),希望能否相互交流溝通問題:


IPV6支持交流群.png

一、IPV6-Only支持是啥?

首先IPV6,是對IPV4地址空間的擴充。目前當我們用iOS設備連接上Wifi、4G、3G等網絡時,設備被分配的地址均是IPV4地址,但是隨著運營商和企業(yè)逐漸部署IPV6 DNS64/NAT64網絡之后,設備被分配的地址會變成IPV6的地址,而這些網絡就是所謂的IPV6-Only網絡,并且仍然可以通過此網絡去獲取IPV4地址提供的內容??蛻舳讼蚍掌鞫苏埱笥蛎馕?#xff0c;首先通過DNS64 Server查詢IPv6的地址,如果查詢不到,再向DNS Server查詢IPv4地址,通過DNS64 Server合成一個IPV6的地址,最終將一個IPV6的地址返回給客戶端。如圖所示:


NAT64-DNS64-ResolutionOfIPv4_2x.png

在Mac OS 10.11+的雙網卡的Mac機器(以太網口+無線網卡),我們可以通過模擬構建這么一個local IPv6 DNS64/NAT64 的網絡環(huán)境去測試應用是否支持IPV6-Only網絡,大概原理如下:


local_ipv6_dns64_nat64_network_2x.png
  • 參考資料:
    • https://developer.apple.com/library/mac/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW1

二、Apple如何審核支持IPV6-Only?

首先第一點:這里說的支持IPV6-Only網絡,其實就是說讓應用在 IPv6 DNS64/NAT64 網絡環(huán)境下仍然能夠正常運行。但是考慮到我們目前的實際網絡環(huán)境仍然是IPV4網絡,所以應用需要能夠同時保證IPV4和IPV6環(huán)境下的可用性。從這點來說,蘋果不會去掃描IPV4的專有API來拒絕審核通過,因為IPV4的API和IPV6的API調用都會同時存在于代碼中(不過為了減小審核被拒風險,建議將IPV4專有API通過IPV6的兼容API來替換)。

其次第二點:Apple官方聲明iOS9開始向IPV6支持過渡,在iOS9.2+支持通過getaddrInfo方法將IPV4地址合成IPV6地址(The ability to synthesize IPv6 addresses was added to getaddrinfo in iOS 9.2 and OS X 10.11.2)。其提供的Reachability庫在iOS8系統(tǒng)下,當從IPV4切換到IPV6網絡,或者從IPV6網絡切換到IPV4,是無法監(jiān)控到網絡狀態(tài)的變化。也有一些開發(fā)者針對這些Bug詢問Apple的審核部門,給予的答復是只需要在蘋果最新的系統(tǒng)上保證IPV6的兼容性即可。

最后第三點:只要應用的主流程支持IPV6,通過蘋果審核即可。對于不支持IPV6的模塊,考慮到我們現實IPV6網絡的部署還需要一段時間,短時間內不會影響我們用戶的使用。但隨著4G網絡IPV6的部署,這部分模塊還是需要逐漸安排人力進行支持。

追加第四點:如果應用一直直接使用IPV4地址通過NSURLConenction或者NSURLSession進行網絡請求(一般需要服務器允許,且客戶端需要在header中偽裝host);經測試,IPV6網絡環(huán)境下,直接使用IPV4地址在iOS9及以上的系統(tǒng)仍然能夠正常訪問;在iOS8.4及以下不能正常訪問;這一點蘋果的解釋和建議是這樣的:


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.


三、應用如何支持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

只說了NSURLSession和CFNetwork的API不需要改變,但是并沒有提及到NSURLConnection。 從上文的參考資料中,我們看到NSURLSession、NSURLConnection同屬于Cocoa的url loading system,可以猜測出NSURLConnection在ios9上是支持IPV6的。

應用里面的API網絡請求,大家一般都會選擇AFNetworking進行請求發(fā)送,由于歷史原因,應用的代碼基本上都深度引用了AFHTTPRequestOperation類,所以目前API網絡請求均需要通過NSURLConnection發(fā)送出去,所以必須確認NSURLConnection是否支持IPV6. 經過測試,NSURLConnection在最新的iOS9系統(tǒng)上是支持IPV6的。

3.2 Cocoa的URL Loading System從iOS哪個版本開始支持IPV6?

目前我們的應用最低版本還需要支持iOS7,雖然蘋果只要求最新版本支持IPV6-Only,但是出于對用戶負責的態(tài)度,我們仍然需要搞清楚在低版本上URL Loading System的API是否支持IPV6.

(to fix me, make some experiments)待續(xù)~~~

3.3 Reachability是否需要修改支持IPV6?

我們可以查到應用中大量使用了Reachability進行網絡狀態(tài)判斷,但是在里面卻使用了IPV4的專用API。

Pods:ReachabilityAF_INET Files:Reachability.m struct sockaddr_in Files:Reachability.h , Reachability.m

那Reachability應該如何支持IPV6呢?
(1)目前Github的開源庫Reachability的最新版本是3.2,蘋果也出了一個Support IPV6 的Reachability的官方樣例,我們比較了一下源碼,跟Github上的Reachability沒有什么差異。
(2)我們通常都是通過一個0.0.0.0 (ZeroAddress)去開啟網絡狀態(tài)監(jiān)控,經過我們測試,在iOS9以上的系統(tǒng)上IPV4和IPV6網絡環(huán)境均能夠正常使用;但是在iOS8上IPV4和IPV6相互切換的時候無法監(jiān)控到網絡狀態(tài)的變化,可能是因為蘋果在iOS8上還并沒有對IPV6進行相關支持相關。(但是這仍然滿足蘋果要求在最新系統(tǒng)版本上支持IPV6的網絡)。
(3)當大家都在要求Reachability添加對于IPV6的支持,其實蘋果在iOS9以上對Zero Address進行了特別處理,官方發(fā)言是這樣的:


reachabilityForInternetConnection: This monitors the address 0.0.0.0,
which reachability treats as a special token that causes it to actually
monitor the general routing status of the device, both IPv4 and IPv6.


+ (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]; }

綜上所述,Reachability不需要做任何修改,在iOS9上就可以支持IPV6和IPV4,但是在iOS9以下會存在bug,但是蘋果審核并不關心。

四、底層的socket API如何同時支持IPV4和IPV6?

由于在應用中使用了網絡診斷的組件,大量使用了底層的 socket API,所以對于IPV6支持,這塊是個重頭戲。如果你的應用中使用了長連接,其必然會使用底層socket API,這一塊也是需要支持IPV6的。 對于Socket如何同時支持IPV4和IPV6,可以參考谷歌的開源庫CocoaAsyncSocket.

下面我針對我們的開源 網絡診斷組件, 說一下是如何同時支持IPV4和IPV6的。
開源地址:https://github.com/Lede-Inc/LDNetDiagnoService_IOS.git
這個網絡診斷組件的主要功能如下:

  • 本地網絡環(huán)境的監(jiān)測(本機IP+本地網關+本地DNS+域名解析);
  • 通過TCP Connect監(jiān)測到域名的連通性;
  • 通過Ping 監(jiān)測到目標主機的連通耗時;
  • 通過traceRoute監(jiān)測設備到目標主機中間每一個路由器節(jié)點的ICMP耗時;

4.1 IP地址從二進制到符號的轉化

之前我們都是通過inet_ntoa()進行二進制到符號,這個API只能轉化IPV4地址。而inet_ntop()能夠兼容轉化IPV4和IPV6地址。 寫了一個公用的in6_addr的轉化方法如下:

//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

相當于我們在終端中輸入ifconfig命令獲取字符串,然后對ifconfig結果字符串進行解析,獲取其中en0(Wifi)、pdp_ip0(移動網絡)的ip地址。

注意:
(1)在模擬器和真機上都會出現以FE80開頭的IPV6單播地址影響我們判斷,所以在這里進行特殊的處理(當第一次遇到不是單播地址的IP地址即為本機IP地址)。
(2)在IPV6環(huán)境下,真機測試的時候,第一個出現的是一個IPV4地址,所以在IPV4條件下第一次遇到單播地址不退出。

+ (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 iPhoneif ([[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 Stringaddress = [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

其實是在IPV4獲取網關地址的源碼的基礎上進行了修改,初開把AF_INET->AF_INET6, sockaddr -> sockaddr_in6之外,還需要注意如下修改,就是拷貝的地址字節(jié)數。去掉了ROUNDUP的處理。 (解析出來的地址老是少了4個字節(jié),結果是偏移量搞錯了,糾結了半天),具體參考源碼庫。

/* 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 IPV4for (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 IPV6for (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

IPV4時只需要通過res_ninit進行初始化就可以獲取,但是在IPV6環(huán)境下需要通過res_getservers()接口才能獲取。

+(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

在IPV4網絡下我們通過gethostname獲取,而在IPV6環(huán)境下,通過新的gethostbyname2函數獲取。

//ipv4 phot = gethostbyname(hostN);//ipv6phot = gethostbyname2(hostN, AF_INET6);

4.5 ping方案支持IPV6

Apple的官方提供了最新的支持IPV6的ping方案,參考地址如下:
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

其實是通過創(chuàng)建socket套接字模擬ICMP報文的發(fā)送,以計算耗時;
兩個關鍵的地方需要注意:
(1)IPV6中去掉IP_TTL字段,改用跳數IPV6_UNICAST_HOPS來表示;
(2)sendto方法可以兼容支持IPV4和IPV6,但是需要最后一個參數,制定目標IP地址的大小;因為前一個參數只是指明了IP地址的開始地址。千萬不要用統(tǒng)一的sizeof(struct sockaddr), 因為sockaddr_in 和 sockaddr都是16個字節(jié),兩者可以通用,但是sockaddr_in6的數據結構是28個字節(jié),如果不顯式指定,sendto方法就會一直返回-1,erroNo報22 Invalid argument的錯誤。

關鍵代碼如下:(完整代碼參考開源組件)

//構造通用的IP地址結構stuck sockaddrNSString *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];//創(chuàng)建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)//發(fā)送成功返回值等于發(fā)送消息的長度 ssize_t sentLen = sendto(send_sock, cmsg, sizeof(cmsg), 0, (struct sockaddr *)destination, isIPV6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in));
http://www.jianshu.com/p/a6bab07c4062

總結

以上是生活随笔為你收集整理的iOS应用支持IPV6,就那点事儿的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 精品国产一| 乱色欧美 | 桃谷绘里香番号 | 色综合综合网 | 丝袜中文字幕 | 日本美女一区二区三区 | 欧美人与动物xxx | 免费在线看视频 | 中文无码熟妇人妻av在线 | 已满十八岁免费观看全集动漫 | 秋霞午夜鲁丝一区二区老狼 | 久久久.com | 色xxxxx| 国产不卡一区 | 永久免费的网站入口 | 亚洲码国产精品高潮在线 | 偷偷久久| 国产精品爽爽久久久久久 | 99精品国产成人一区二区 | 美女黄视频大全 | 北条麻妃久久精品 | 黄色com| 一本黄色片| 欧美69式性猛交 | 在线免费黄 | 天堂一二三区 | 就去色av | 国产女人水真多18毛片18精品 | 视频一二三区 | 黄色a一级视频 | 亚洲调教欧美在线 | 大片av| 一品毛片 | 黄色一级片免费在线观看 | 国产日韩精品一区 | 欧美在线影院 | 雷电将军和丘丘人繁衍后代视频 | 国产精品电影网站 | 狠狠狠狠狠狠干 | 亚洲色图狠狠干 | 看全色黄大色黄大片大学生 | 国产手机视频在线 | 九九少妇| 日本强好片久久久久久aaa | 亚洲精品aⅴ中文字幕乱码 国产精品调教视频 | 久久久久久无码午夜精品直播 | 亚洲av无码一区二区二三区 | www.蜜臀 | 美日韩成人 | 国产精品地址 | 色爽黄| 亚洲欧美综合网 | 日本三级中文字幕在线观看 | 久久久久久久麻豆 | 好吊一区二区三区 | 久久久久久中文字幕 | 成人在线激情 | 最近中文字幕在线观看视频 | 亚洲精品成人a | 精品一区二区在线免费观看 | 天天插天天爽 | 亚洲天堂资源在线 | 国产一级片a | www亚洲| 国产男女无遮挡猛进猛出 | 天天干天天操av | 欧美激情aaa | 免费无码毛片一区二三区 | 亚洲成人日韩在线 | 久久久久久亚洲av毛片大全 | www.日韩| 日本午夜在线 | 久久九九久精品国产免费直播 | 欧美乱三级 | 国产一区二区三区视频在线观看 | 好男人www日本| 少妇人妻综合久久中文字幕 | 色吧在线视频 | 欧美日韩在线成人 | 免费毛片基地 | 荫蒂被男人添免费视频 | 国产精品免费入口 | 国产精品一区二区三区久久久 | 国产精品成熟老女人 | 欧美整片sss | 色性网站 | 人人射人人爱 | 中文字幕在线观看日本 | 欧美亚洲在线视频 | 亚洲一级精品 | 欧美视频免费在线观看 | 美女视频久久久 | 国产精品视频免费看 | 中国国产毛片 | 欧美黄色录像 | 97免费人妻无码视频 | 山村大伦淫第1部分阅读小说 | 99精品视频免费观看 | 日韩精品免费一区二区三区 |