適配IPV6
在WWDC2015上蘋果公司宣布iOS9將支持純IPV6的網絡服務。自從5月初Apple明文規定所有開發者在6月1號以后提交新版本需要支持IPV6-Only的網絡,什么是IPV6 ? Apple如何審核IPV6?如何支持IPV6?應用中哪些模塊目前不支持IPV6?為確保現有的應用兼容,我們又應該注意那些東西呢?如果我要進行本地測試,應該如何搭建IPV6環境?
關鍵詞:WWDC2015 IPV6-Only
一、什么是IPV6
首先IPV6,是對IPV4地址空間的擴充。目前當我們用iOS設備連接上Wifi、4G、3G等網絡時,設備被分配的地址均是IPV4地址,但是隨著運營商和企業逐漸部署IPV6 DNS64/NAT64網絡之后,設備被分配的地址會變成IPV6的地址,而這些網絡就是所謂的IPV6-Only網絡,并且仍然可以通過此網絡去獲取IPV4地址提供的內容。客戶端向服務器端請求域名解析,首先通過DNS64 Server查詢IPv6的地址,如果查詢不到,再向DNS Server查詢IPv4地址,通過DNS64 Server合成一個IPV6的地址,最終將一個IPV6的地址返回給客戶端。
二、Apple如何審核支持IPV6-Only
1、簡單來講讓應用能夠在IPv6 DNS64/NAT64網絡環境下仍然能夠正常運行,即為應用支持了IPV6-Only網絡。但目前我們所能使用到的網絡環境仍然是IPV4網絡,所以應用需要同時支持IPV4以及IPV6網絡環境。
2、Apple官方規定iOS9開始向IPV6過度,并在iOS9.2+上支持IPV4地址合成IPV6地址。目前蘋果官方提供的Reachability庫在iOS8系統下無法實現IPV4與IPV6之間的相互切換,所以蘋果官方聲明只需要在蘋果最新的系統上保證支持IPV6的兼容即可。
3、由于目前4G網絡的IPV6部署還不夠完善,所以應用只需要支持主流程兼容IPV6,通過蘋果審核即可。對于不支持IPV6的模塊段時間內不會影響用戶使用,但是后期仍需要進行支持。
三、如何支持IPV6
Apple官方給出以下支持IPV6的標準:
1.UseHigh-LevelNetworking Frameworks;
2. Don’tUseIP Address Literals;
3.CheckSourceCodeforIPv6 DNS64/NAT64Incompatibilities;
4.UseSystemAPIstoSynthesize IPv6 Addresse;
3.1 NSURLConnection是否支持IPV6?
官方給出的聲明只說NSURLSession和CFNetwork的API不需要改變,但是并沒有提及到NSURLConnection相關信息。從NSURLSession、NSURLConnection同屬于Cocoa的url loading system,可以猜測NSURLConnection在iOS9上支持IPV6。但是目前AFNetwroking庫已經推出支持IPV6的3.0版本,使得開發者必須升級AFNetworking并重寫網絡請求。
3.2 Reachability是否需要支持IPV6?
根據實際應用中開發者提出的各種網絡切換問題(通過ZeroAddress開啟網絡監控)蘋果官方給出的相關解釋說明Reachability不需要做任何修改,并且蘋果審核時不關心在iOS9一下Reachability存在的BUG,只關心iOS9以上是否支持。
四、底層的socket API如何同時支持IPV4和IPV6?
應用中大量使用了包含底層的socket API的網絡診斷組件,所以支持IPV6十分重。應用的長連接需要支持IPV6,對于Socket如何同時支持IPV4和IPV6,可以參考谷歌的開源庫CocoaAsyncSocket.
4.1、IP地址從二進制到符號的轉化
話不多說直接上代碼:
//for IPV6
+(NSString*)formatIPV6Address:(structin6_addr)ipv6Addr
{
NSString*address =nil;
chardstStr[INET6_ADDRSTRLEN];
charsrcStr[INET6_ADDRSTRLEN];
memcpy(srcStr, &ipv6Addr,sizeof(structin6_addr));
if(inet_ntop(AF_INET6, srcStr,dstStr,INET6_ADDRSTRLEN)!=NULL){
address = [NSStringstringWithUTF8String:dstStr];
}
returnaddress;
}
//for IPV4
+(NSString*)formatIPV4Address:(structin_addr)ipv4Addr{
NSString*address =nil;
chardstStr[INET_ADDRSTRLEN];
charsrcStr[INET_ADDRSTRLEN];memcpy(srcStr, &ipv4Addr,sizeof(structin_addr));
if(inet_ntop(AF_INET, srcStr, dstStr,INET_ADDRSTRLEN) !=NULL){
address = [NSStringstringWithUTF8String:dstStr];
}
returnaddress;
}
4.2、本機IP獲取支持IPV6
類似于終端輸入ifconfig命令獲取字符串,然后解析獲取其中的en0(Wifi)、padp_ip0(移動網絡)的IP地址。
注意:
1、在模擬器和真機上都會出現以FE80開頭的IPV6單播地址響應我們的判斷,所以要注意第一次遇到不是單播地址的IP即為本機IP地址。
2、在IPV6環境下,真機測試時第一個出現的是IPV4地址,所以在IPV4條件下第一次遇到單播地址不退出。
代碼;
+ (NSString *)deviceIPAdress
{
while(temp_addr !=NULL) {
NSLog(@"ifa_name===%@",[NSStringstringWithUTF8String: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 = [selfformatIPV4Address:((structsockaddr_in *)temp_addr->ifa_addr)->sin_addr];
}
//如果是IPV6地址
elseif(temp_addr->ifa_addr->sa_family == AF_INET6){
address = [selfformatIPV6Address:((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的方法請移步支持IPV6方法總結
五、對于兼容IPV6需要注意的事項
5.1、最好不要使用底層的API。
下圖展示的藍色部分的這些API都是不存在兼容性問題的,而我們平時自己用的包括那些第三方的網絡庫大部分都是用的這些API。
Networking frameworks and API layers
大部分情況下我們用高級的API完全能實現需求,而且高級的API封裝的很好,并且方便使用,對于IPV6的適配也幫我們做好了,例如ShareSDK等。就像之前提到的哪有,使用底層AIP會有大量的工作需要我們自己完成,所以可能更容易出現BUG。
5.2不要用IP地址
比如下面這個API,nodename這個參數不要傳IP地址,而應該用域名。
這個方法會在Reachability中用到。常用的網絡請求庫AFNetworking最近剛更新版本就是使用了這個方法。如果使用AFNetworking且應用需要提交到App store上需要盡快更新版本并做好相關適配。
5.3檢查不兼容IPV6的代碼
全局搜一下工程里有沒有如下這些API,這些都是針對IPv4做處理的,有的話就刪除。
inet_addr()
inet_aton()
inet_lnaof()
inet_makeaddr()
inet_netof()
inet_network()
inet_ntoa()
inet_ntoa_r()
bindresvport()
getipv4sourcefilter()
setipv4sourcefilter()
對應IPV4做IPV6處理
IPV4
IPV6
AF_INET
AF_INET6
PE_INET
PE_INET6
struct in_addr
Struct in_addr6
struct sockadd_in
struct sockaddr_in6
kDNSServiceProtocol_IPv4
kDNSServiceProtocol_IPv6
IPv4--IPv6
六、本地搭建IPv6測試環境
最后我們如何搭建一個測試的IPv6環境呢?其實很簡單,我們可以通過Mac做一個熱點,然后讓iPhone連接這個Wifi。區別是這次我們產生的是一個本地的IPv6 DNS64/NAT64網絡,這項功能是OS X 10.11新加的。和我們以前開啟熱點方式不一樣的地方在于,我們在“System
Preferences”界面選中“Sharing”的同時,要按住“Option”鍵。
之后在“Sharing”界面中,我們會看到和之前不一樣的地方,就是紅框所標的地方,多了一個叫“Create NAT64 Network”的選框,選中它。
之后就是按照正常的創建熱點的流程走完就行了。
現在我們用iPhone連接上這個剛創建好的熱點就可以測試了,注意此時要把iPhone設成飛行模式,以保證只用Wi-Fi上網。
七、iOS IPv6最新升級攻略
蘋果商店6月1日起,強制app需要支持IPv6-only的網絡。
iOS IPv6最新升級攻略:
1,官方Reachability
2,微信SDK
iOS平臺微信SDK下載地址:https://res.wx.qq.com/open/zh_CN/htmledition/res/dev/download/sdk/WeChatSDK1.7.zip
微信SDK已支持IPv6,請iOS開發者及時升級
由于蘋果App Store政策調整,所有iOS應用必須支持IPv6。iOS平臺微信SDK最新的1.7版已支持IPv6,請開發者及時升級App中的微信SDK。
微信團隊
2016年05月12日
3,微博SDK
https://github.com/sinaweibosdk/weibo_ios_sdk
關于ipv6支持的問題
由于蘋果商店6月1日起,強制app需要支持ipv6-only的網絡。微博sdk這邊也做了支持,更新了使用的底層網絡代碼,包括reachability庫。
附錄:
百度百科對IPV6解釋:http://baike.baidu.com/view/5228.htm