quic協(xié)議

此文章為引用,原文鏈接:http://www.itdecent.cn/p/2501a618ad1b




一、首先聊一聊這些年蘋果爸爸對(duì)網(wǎng)絡(luò)層的改變

1、在2003年隨著第一版Safari的發(fā)布就發(fā)布了NSURLConnection。 作為網(wǎng)絡(luò)基礎(chǔ)架構(gòu),這些年也服務(wù)了成千上萬(wàn)的iOS和Mac OS程序,也做得相當(dāng)?shù)牟诲e(cuò)。

2、2013年蘋果推出iOS 7,這個(gè)版本的iOS被稱為革命性的iOS,而我們以前所用到的NSURLConnection這個(gè)網(wǎng)絡(luò)庫(kù)也被蘋果爸爸給重構(gòu), 并且重新命名為NSURLSession。

3、2014年的iOS 8蘋果爸爸宣布正式淘汰NSURLConnection,同時(shí)發(fā)布了App Extensions。

4、2015年iOS 9蘋果爸爸讓網(wǎng)絡(luò)變得更加安全了。

(1)App Transport Security (ATS):核心目的是防止意外泄露用戶的敏感數(shù)據(jù),ATS加強(qiáng)了NSURLSession的默認(rèn)策略,現(xiàn)在的NSURLSession不允許明文的HTTP加載,他只會(huì)使用HTTPS連接。

(2)NSURLSession支持HTTP/2協(xié)議:如果已經(jīng)在程序中使用NSURLSession,所有的這些都會(huì)自動(dòng)轉(zhuǎn)換。HTTP/2協(xié)議已經(jīng)無(wú)縫集成到NSURLSession的API中,不需要修改任何代碼工程就可支持HTTP/2協(xié)議。

(3)watchOS 支持NSURLSession:之前iWatch通過藍(lán)牙和iphone連接,iphone下載完成在通過藍(lán)牙傳到watch?,F(xiàn)在watch可以通過使用NSURLSession自己下載。

(4)共享cookies:iOS8推出了App Extension,之前App與其Extension都默認(rèn)對(duì)數(shù)據(jù)的持有進(jìn)行獨(dú)立處理,就像放在兩個(gè)不同的數(shù)據(jù)集合里,而現(xiàn)在可以讓App和其Extension共享同一個(gè)數(shù)據(jù)集合。具體代碼如下:

(5)增加NSURLSessionStreamTask:以前我們使用NSInputStream/NSOutputStream來進(jìn)行一些非HTTP的連接, 例如利用TCP連接一臺(tái)遠(yuǎn)程的服務(wù)器等等, 現(xiàn)在我們有了NSURLSessionStreamTask讓我們更簡(jiǎn)單地實(shí)現(xiàn)以上功能。

6、2016年 iOS 10新增NSURLSessionTaskMetrics和NSURLSessionTaskTransactionMetrics:對(duì)發(fā)送請(qǐng)求/DNS查詢/TLS握手/請(qǐng)求響應(yīng)等各種環(huán)節(jié)時(shí)間上的統(tǒng)計(jì)。更易于我們檢測(cè), 分析我們的請(qǐng)求緩慢到底是發(fā)生在哪個(gè)環(huán)節(jié),并對(duì)此進(jìn)行優(yōu)化提升我們APP的性能。

7、2017年iOS 11蘋果爸爸在網(wǎng)絡(luò)層做了新增和優(yōu)化了。

(1)提供了NSProgressReporting協(xié)議,且NSURLSessionTask實(shí)現(xiàn)了這個(gè)協(xié)議,讓我們能夠獲得progress對(duì)象,這個(gè)progress對(duì)象可以以0~1.0的方式告訴你當(dāng)前進(jìn)度,而不用你自己去拿到已獲得的數(shù)據(jù)量去除以需要獲得的數(shù)據(jù)總量從而得出進(jìn)度。然后這個(gè)progress對(duì)象跟NSURLSessionTask的綁定是雙向的:你調(diào)用progress對(duì)象的cancel、pause、resume也會(huì)使得task變?yōu)閏ancel、pause、resume,反之亦然。

(2)新增waitsForConnectivity屬性,以前進(jìn)行網(wǎng)絡(luò)調(diào)用時(shí),如果網(wǎng)絡(luò)不通,那么系統(tǒng)就會(huì)報(bào)個(gè)錯(cuò)告訴你網(wǎng)絡(luò)不通。這時(shí)候你要么輪詢要么讓用戶手動(dòng)retry,然后網(wǎng)絡(luò)通了請(qǐng)求才能發(fā)送出去?,F(xiàn)在只需要把NSURLSessionConfiguration的waitsForConnectivity設(shè)置成YES,這樣如果請(qǐng)求發(fā)送的時(shí)候網(wǎng)絡(luò)不通,那么這個(gè)請(qǐng)求就會(huì)等到網(wǎng)絡(luò)通了的時(shí)候再發(fā)出去。

(3)在NSURLSessionTask的delegate里面新增了一個(gè)方法urlSession:task:willBeginDelayedRequest:completionHandler:系統(tǒng)在發(fā)起請(qǐng)求之前會(huì)調(diào)一個(gè)這個(gè)回調(diào),然后在這個(gè)completionHandler里面你告訴系統(tǒng)這個(gè)請(qǐng)求是否要發(fā)出去,是否要修改。(因?yàn)閯?chuàng)建的后臺(tái)請(qǐng)求在還沒發(fā)出去的時(shí)候可能因?yàn)樯舷挛淖兓脑驅(qū)е逻@個(gè)請(qǐng)求無(wú)意義)

(4)earliestBeginDate屬性,在后臺(tái)請(qǐng)求的時(shí)候以前系統(tǒng)不知道什么時(shí)候去發(fā)起你的請(qǐng)求才是最合適的 ,現(xiàn)在給task設(shè)置一個(gè)earliestBeginDate,系統(tǒng)在這之前是不會(huì)發(fā)起請(qǐng)求的。

(5)iOS 11可以通過設(shè)置NSURLSessionTask的countOfBytesClientExpectsToSend和countOfBytesClientExpectsToReceive來讓系統(tǒng)更好地調(diào)度你的后臺(tái)網(wǎng)絡(luò)任務(wù)。

(6)multipathServiceType:移動(dòng)設(shè)備多路協(xié)議,這使得移動(dòng)設(shè)備的TCP包可以在這兩個(gè)(多個(gè))鏈路上隨意切換著發(fā)(同時(shí)開啟兩個(gè)流量鏈路),而不必?cái)嗑€重連。

(7)iOS 11支持ECN(顯式擁塞通知)可以最大化的使用網(wǎng)絡(luò)帶寬,減少包的重發(fā)次數(shù),降低延遲。還有iOS 11里的網(wǎng)絡(luò)操作被移動(dòng)到User Space去了。iOS11支持Brotli壓縮算法。iOS11更新了Public Suffix List。

8、未來會(huì)有哪些變化

(1)TLS1.3:蘋果要把網(wǎng)絡(luò)庫(kù)整體遷移到支持TLS1.3,年底TLS1.3的標(biāo)準(zhǔn)應(yīng)該能出來。現(xiàn)在基于TLS1.3草稿的實(shí)現(xiàn)可以弄下來自己測(cè)試著玩了。最新的TLS1.3草稿已經(jīng)出到21了:draft-ietf-tls-tls13-21。

(2)QUIC:Google搞了個(gè)QUIC,蘋果在跟進(jìn)。QUIC可以理解成UDP實(shí)現(xiàn)的TCP+TLS+HTTP/2集合體。主要是提高了數(shù)據(jù)傳輸效率和鏈接效率。目前QUIC的開發(fā)才剛剛開始,項(xiàng)目網(wǎng)站提供了玩具客戶端和玩具服務(wù)端給大家玩:Playing with QUIC。

二、聊一聊NSURLSession

1、支持data, ftp, http(s)協(xié)議, 同時(shí)支持代理服務(wù)器和socks網(wǎng)關(guān).

2、支持http/1.1, http/2, spdy協(xié)議, 但同時(shí)需要服務(wù)器支持ALPN和NPN.

3、ALPN(Application Layer Protocol Negotiation,應(yīng)用層協(xié)議協(xié)商)

4、NPN(Next Protocol Negotiation,下一代協(xié)議協(xié)商)

5、NPN是服務(wù)端發(fā)送它支持的HTTP協(xié)議列表, 供客戶端選擇; 而ALPN則相反,由客戶端發(fā)送它支持的HTTP協(xié)議列表, 供服務(wù)端選擇。如果缺少NPN/ALPN其中一個(gè), 則無(wú)法使用HTTP/2通信。

想詳細(xì)了解HTTP/2的可以參考這兩篇文章為什么我們應(yīng)該盡快支持 ALPN談?wù)?HTTP/2 的協(xié)議協(xié)商機(jī)制

6、NSURLSession相關(guān)類為 :

? ? ?? NSURLSession

? ? ?? NSURLSessionConfiguration

? ? ?? NSURLSessionDelegate

? ? ?? NSURLSessionTask

? ? ?? NSURLSessionTaskMetrics

? ? ?? NSURLSessionTaskTransactionMetrics

用一個(gè)簡(jiǎn)單的圖來表示一下他們各個(gè)類之間的關(guān)系:

(一)同名類NSURLSession

初始化方式:

? 1、 [NSURLSession sharedSession];全局單例session,有一定的局限性。

? 2、自定義配置文件,設(shè)置代理

?? [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];

? ? [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

3、后臺(tái)session(由NSURLSessionConfiguration)配置。

(二)NSURLSessionConfiguration

NSURLSessionConfiguration 有三個(gè)類方法,這很好地說明了 NSURLSession 設(shè)計(jì)時(shí)所考慮的不同的使用場(chǎng)景。

1、+defaultSessionConfiguration 返回一個(gè)標(biāo)準(zhǔn)的 configuration,共享 NSHTTPCookieStorage,共享 NSURLCache 和共享 NSURLCredentialStorage。

2、+ephemeralSessionConfiguration 返回一個(gè)預(yù)設(shè)配置,這個(gè)配置中不會(huì)對(duì)緩存,Cookie 和證書進(jìn)行持久性的存儲(chǔ)。這對(duì)于實(shí)現(xiàn)像秘密瀏覽這種功能來說是很理想的。

3、+backgroundSessionConfiguration:(NSString *)identifier 創(chuàng)建一個(gè)后臺(tái) session。后臺(tái) session 不同于常規(guī)的,普通的 session,它甚至可以在應(yīng)用程序掛起,退出或者崩潰的情況下運(yùn)行上傳和下載任務(wù)。

NSURLSessionConfiguration擁有20多個(gè)配置屬性:

1、基本配置

(1)HTTPAdditionalHeaders 指定了一組默認(rèn)的可以設(shè)置出站請(qǐng)求的數(shù)據(jù)頭。這對(duì)于跨 session 共享信息,如內(nèi)容類型,語(yǔ)言,用戶代理和身份認(rèn)證,是很有用的。

(2)networkServiceType 對(duì)標(biāo)準(zhǔn)的網(wǎng)絡(luò)流量,網(wǎng)絡(luò)電話,語(yǔ)音,視頻,以及由一個(gè)后臺(tái)進(jìn)程使用的流量進(jìn)行了區(qū)分。

(3)allowsCellularAccess 和 discretionary 被用于節(jié)省通過蜂窩網(wǎng)絡(luò)連接的帶寬。對(duì)于后臺(tái)傳輸?shù)那闆r,推薦大家使用 discretionary 這個(gè)屬性,因?yàn)閍llowsCellularAccess會(huì)把 WiFi 和電源的可用性考慮在內(nèi)。

(4)timeoutIntervalForRequest 和 timeoutIntervalForResource 分別指定了對(duì)于請(qǐng)求和資源的超時(shí)間隔。

(5)HTTPMaximumConnectionsPerHost可以在需要時(shí)限制連接到特定主機(jī)的數(shù)量。

(6)sessionSendsLaunchEvents 指定該 session 是否應(yīng)該從后臺(tái)啟動(dòng)。

(7)connectionProxyDictionary 指定了 session 連接中的代理服務(wù)器。

(8)waitsForConnectivity如果請(qǐng)求發(fā)送的時(shí)候網(wǎng)絡(luò)不通,那么這個(gè)請(qǐng)求就會(huì)等到網(wǎng)絡(luò)通了的時(shí)候再發(fā)出去。

(9)multipathServiceType多路多協(xié)議網(wǎng)絡(luò)操作這使得移動(dòng)設(shè)備的TCP包可以在這兩個(gè)(多個(gè))鏈路上隨意切換著發(fā)(同時(shí)開啟兩個(gè)流量鏈路),而不必?cái)嗑€重連。效果就是:Wi-Fi和Cellular可以共存,相互輔助。

(10)NSURLSessionMultipathServiceTypeHandover(可靠模式)

(11)這種模式下優(yōu)先考慮的是鏈接的可靠性。只有在Wi-Fi信號(hào)不好的時(shí)候,流量才會(huì)走Cellular。如果Wi-Fi信號(hào)好,但是Wi-Fi很慢,這時(shí)候也不會(huì)切到Cellular鏈路。

(12)NSURLSessionMultipathServiceTypeInteractive(低延時(shí)模式)

(13)這種模式下優(yōu)先考慮的是鏈接的低延時(shí)。系統(tǒng)會(huì)看Wi-Fi快還是Cellular快。如果Cellular比Wi-Fi快,哪怕此時(shí)Wi-Fi信號(hào)很好,系統(tǒng)也會(huì)把流量切到Cellular鏈路。

(14)NSURLSessionMultipathServiceTypeAggregate(混合模式)

(15)在這種模式下,Wi-Fi和Cellular會(huì)同時(shí)起作用。如果Wi-Fi是1G帶寬,Cellular也是1G帶寬,那么你的設(shè)備就能享受2G帶寬。(不能用于生產(chǎn)環(huán)境)

(16)需要注意的是,Multipath Protocols for Mobile Devices這個(gè)功能同時(shí)也需要服務(wù)端支持MPTCP(Multipath TCP)才行,如果服務(wù)端不支持的話,光客戶端支持沒用。linux起了一個(gè)項(xiàng)目在做這個(gè)事情,項(xiàng)目地址:https://multipath-tcp.org。有興趣的同學(xué)可以自己去看一下。

2、Cookie策略

HTTPCookieStorage存儲(chǔ)了session所使用的cookie。兩種初始化方式

(1)[NSHTTPCookieStorage sharedHTTPCookieStorage];

(2)[NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:@"identifier"];iOS 9新增。

(3)NSHTTPCookieAcceptPolicy決定了什么情況下 session 應(yīng)該接受從服務(wù)器發(fā)出的 cookie。

3、安全策略

(1)URLCredentialStorage存儲(chǔ)了NSURLSession所使用的證書,默認(rèn)使用+sharedCredentialStorage單例對(duì)象。

(2)TLSMinimumSupportedProtocol和TLSMaximumSupportedProtocol確定session是否支持SSL協(xié)議。

4、緩存策略

(1)URLCache是 session 使用的緩存。默認(rèn)情況下會(huì)使用 NSURLCache 的 +sharedURLCache 這個(gè)單例對(duì)象。

(2)requestCachePolicy 指定了一個(gè)請(qǐng)求的緩存響應(yīng)應(yīng)該在什么時(shí)候返回。

5、自定義協(xié)議

(1)protocolClasses 用來配置特定某個(gè) session 所使用的自定義協(xié)議(該協(xié)議是 NSURLProtocol 的子類)的數(shù)組。

(三)NSURLSessionDelegate

session管理的一組tasks共享一個(gè)代理, 不想實(shí)現(xiàn)代理方法時(shí), 代理傳nil即可。代理協(xié)議分為 :

(1)NSURLSessionDelegate : session-level的代理方法。

(2)NSURLSessionTaskDelegate : task-level面向all的代理方法。

(3)NSURLSessionDataDelegate : task-level面向data和upload的代理方法。

(4)NSURLSessionDownloadDelegate : task-level的面向download的代理方法。

(5)NSURLSessionStreamDelegate : task-level的面向stream的代理方法。

(四)NSURLSessionTask

當(dāng)一個(gè) NSURLSessionDataTask 完成時(shí),它會(huì)帶有相關(guān)聯(lián)的數(shù)據(jù),一般來說,服務(wù)端對(duì)于一個(gè)上傳任務(wù)的響應(yīng)也會(huì)有相關(guān)數(shù)據(jù)返回,所以 NSURLSessionUploadTask 繼承自 NSURLSessionDataTask。

task 是由一個(gè) NSURLSession 創(chuàng)建的。每個(gè) task 的構(gòu)造方法都對(duì)應(yīng)有或者沒有 completionHandler 這個(gè) block 的兩個(gè)版本,例如:有這樣兩個(gè)構(gòu)造方法 –dataTaskWithRequest: 和 –dataTaskWithRequest:completionHandler:。

(1)NSURLSessionTask : Task的抽象基類。

(2)NSURLSessionDataTask : 以NSData的形式接收一個(gè)URLRequest的內(nèi)容。

(3)NSURLSessionUploadTask : 上傳NSData或者本地磁盤中的文件, 完成后以NSData的形式接收一個(gè)URLRequest的響應(yīng)。

(4)NSURLSessionDownloadTask : 下載完成后返回臨時(shí)文件在本地磁盤的URL路徑。

(5)NSURLSessionStreamTask : 用于建立一個(gè)TCP/IP連接。

以前我們使用NSInputStream/NSOutputStream來進(jìn)行一些非HTTP的連接, 例如利用TCP連接一臺(tái)遠(yuǎn)程的服務(wù)器等等, 現(xiàn)在我們有了NSURLSessionStreamTask讓我們更簡(jiǎn)單地實(shí)現(xiàn)以上功能。

NSURLSessionStreamTask的特性 :

(1)更輕松地使用TCP進(jìn)行通信。

(2)替代NSInputStream/NSOutputStream, 提供更優(yōu)的API。

(3)異步讀寫API。

(4)能自動(dòng)通過HTTP代理, 連接一個(gè)遠(yuǎn)程服務(wù)器。

(5)輕松轉(zhuǎn)換成NSStream。

(五)NSURLSessionTaskMetrics 和 NSURLSessionTaskTransactionMetrics

對(duì)發(fā)送請(qǐng)求/DNS查詢/TLS握手/請(qǐng)求響應(yīng)等各種環(huán)節(jié)時(shí)間上的統(tǒng)計(jì)。更易于我們檢測(cè),分析我們App的請(qǐng)求緩慢到底是發(fā)生在哪個(gè)環(huán)節(jié),并對(duì)此進(jìn)行優(yōu)化提升我們APP的性能。

NSURLSessionTaskMetrics對(duì)象與NSURLSessionTask對(duì)象一一對(duì)應(yīng)。每個(gè)NSURLSessionTaskMetrics對(duì)象內(nèi)有3個(gè)屬性 :

(1)taskInterval : task從開始到結(jié)束總共用的時(shí)間

(2)redirectCount : task重定向的次數(shù)

(3)transactionMetrics : 一個(gè)task從發(fā)出請(qǐng)求到收到數(shù)據(jù)過程中派生出的每個(gè)子請(qǐng)求, 它是一個(gè)裝著許多NSURLSessionTaskTransactionMetrics對(duì)象的數(shù)組。每個(gè)對(duì)象都代表下圖的一個(gè)子

API很簡(jiǎn)單,就一個(gè)方法 : - (void)URLSession: task: didFinishCollectingMetrics:, 當(dāng)收集完成的時(shí)候就會(huì)調(diào)用該方法。

fetchStart : 開始發(fā)起請(qǐng)求.

domainLookupStart : 發(fā)送DNS請(qǐng)求, 域名->IP地址

domainLookupEnd : DNS請(qǐng)求完成, 拿到IP地址

connectStart : 與遠(yuǎn)程服務(wù)器開始建立TCP連接

secureConnectionStart : HTTPS的TLS握手開始

secureConnectionEnd : HTTPS的TLS握手完成connectEnd : 與服務(wù)器建立起了TCP連接

requestStart : 開始傳輸HTTP header第一個(gè)字節(jié)的時(shí)間(遠(yuǎn)程/緩存)

requestEnd : HTTP最后一個(gè)字節(jié)傳輸完成的時(shí)間(遠(yuǎn)程/緩存)

responseStart : 從服務(wù)器得到數(shù)據(jù)(遠(yuǎn)程/緩存)

responseEnd : 從服務(wù)器接受完最后一個(gè)字節(jié)的數(shù)據(jù)(遠(yuǎn)程/緩存)

(六)NSSession的整個(gè)工作流程

(1)身份驗(yàn)證或TLS握手:

? ? ? ? 這是所有task都必須經(jīng)歷的一個(gè)過程. 當(dāng)一個(gè)服務(wù)器請(qǐng)求身份驗(yàn)證或TLS握手期間需要提供證書的話會(huì)調(diào)用這個(gè)代理。另外, 如果連接途中收到服務(wù)器返回需要身份認(rèn)證的response, 也會(huì)調(diào)用這個(gè)代理方法。

(2)重定位response:

? ? ? ? 如果response是HTTP重定位, session會(huì)調(diào)用下面的代理,這里需要調(diào)用completionHandler告訴session是否允許重定位,或者重定位到另一個(gè)URL,或者傳nil表示重定位的響應(yīng)body有效并返回。如果代理沒有實(shí)現(xiàn)該方法,則允許重定位直到達(dá)到最大重定位次數(shù)。

(3)DataTask

? ? ? ? <1> 對(duì)于一個(gè)data task來說,session會(huì)調(diào)用代理決定是否將一個(gè)dataTask轉(zhuǎn)換成download task,然后調(diào)用completion回調(diào)繼續(xù)接收data或下載data。

? ? ? ?<2> 在服務(wù)器傳輸數(shù)據(jù)給客戶端期間, 代理會(huì)周期性地收到

? ? ? ?<3> session會(huì)調(diào)用下面代理詢問你的app是否允許緩存。 如果代理不實(shí)現(xiàn)這個(gè)方法的話,默認(rèn)使用session綁定的Configuration的緩存策略。

(4)DownloadTask

? ? ? ? ?<1>session先會(huì)調(diào)用代理方法。

? ? ? ? <2>在服務(wù)器傳輸數(shù)據(jù)給客戶端期間, 調(diào)用下面代理給用戶傳數(shù)據(jù)。

? ? ? ?<3>當(dāng)用戶暫停下載時(shí),調(diào)用cancelByProducingResumeData:給用戶傳已下好的數(shù)據(jù)。

? ? ? ?<4>如果用戶想要恢復(fù)下載,把剛剛的resumeData以參數(shù)的形式傳給downloadTaskWithResumeData:方法創(chuàng)建新的task繼續(xù)下載。

? ? ? ?<5>如果download task成功完成了,調(diào)用下面代理把臨時(shí)文件的URL路徑給你。此時(shí)你應(yīng)該在該代理方法返回以前讀取他的數(shù)據(jù)或者把文件持久化。

(5)UploadTask

? ? ? ? ?上傳數(shù)據(jù)去服務(wù)器期間, 代理會(huì)周期性收到URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:回調(diào)并獲得上傳進(jìn)度的報(bào)告。

(6)StreamTask

? ? ? ? 如果任務(wù)的數(shù)據(jù)是由一個(gè)stream發(fā)出的, session就會(huì)調(diào)用代理的URLSession:task:needNewBodyStream:方法去獲取一個(gè)NSInputStream對(duì)象并提供一個(gè)新請(qǐng)求的body data。

(7)task completion

? ? ? ? 任何task完成的時(shí)候, 都會(huì)調(diào)用URLSession:task:didCompleteWithError:方法,error有可能為nil(請(qǐng)求成功),不為nil(請(qǐng)求失敗)

(8)銷毀session

? ? ? ?如果你不再需要一個(gè)session了, 一定要調(diào)用它的invalidateAndCancel或finishTasksAndInvalidate方法來釋放session否則會(huì)造成內(nèi)存泄露。

(七)蘋果爸爸建議的最佳網(wǎng)絡(luò)實(shí)踐

1、IPv6

蘋果爸爸說:IPv6各種好,大家快來用。如果你不支持IPv6,爸爸就不讓你上架。要支持IPv6的話,老老實(shí)實(shí)用NSURLSession或者CFNetwork就OK了。

不要做的事情:

(1)不用歷史遺留的IPv4 API。

(2)不要直接用IPv4的地址做鏈接,應(yīng)該用域名去做請(qǐng)求。

(3)發(fā)包前不要做各種檢查:比如你在建立鏈接之前想看一下我當(dāng)前這個(gè)設(shè)備是不是IPv4的地址,這種做法就不行。

(4)不要直接使用socket去發(fā)起請(qǐng)求。

2、不要引入其他的網(wǎng)絡(luò)庫(kù),要使用蘋果自己的API

? ? ?蘋果并不是在說AFNetworking、Alamofire不能用。這些第三方庫(kù)本質(zhì)上還是基于NSURLSession,也就是蘋果的API去開發(fā)的。所以用它們沒問題。蘋果的意思是不希望你使用別的基于Socket開發(fā)的網(wǎng)絡(luò)庫(kù),例如:ACE、Asio這些。

3、一般來說一個(gè)App就一個(gè)NSURLSession就夠了

? ? ?以前遷移NSURLConnection到NSURLSession的時(shí)候,有人每次都創(chuàng)建新的NSURLSession,但事實(shí)上這是沒必要的。各個(gè)并行的NSURLSessionTask可以共享同一個(gè)NSURLSession。如果你使用了多個(gè)NSURLSession的話,記得清理就好,不清理是會(huì)產(chǎn)生內(nèi)存泄漏的。

4、NSURLSession的delegate方法和block方法不要同時(shí)使用

? ? ?如果你用了block,那么delegate就不會(huì)回調(diào)了。這事情僅有兩個(gè)特例是兩個(gè)都回調(diào)的:taskIsWaitingForConnectivity和didReceiveAuthenticateChallenge。

三、了解一下Network Extension Framework

iOS 9 發(fā)布之后,推出NetworkExtension, 它可給系統(tǒng)WiFi列表列表里邊的WiFi設(shè)置密碼 、標(biāo)簽(副標(biāo)題) ?來直接點(diǎn)擊連接。 還可獲取整個(gè)WiFi列表,建立VPN等。

1、iOS 11新增了兩個(gè)類:NEHotSpotConfiguration,NEDNSProxyProvider。

(1)NEHotSpotConfiguration

? ? ? ? NEHotSpotConfiguration可以讓你的智能設(shè)備在鏈接手機(jī)App之后,能夠很方便地通過在手機(jī)App上的操作來實(shí)現(xiàn)熱點(diǎn)的鏈接。例如你買了一個(gè)網(wǎng)絡(luò)攝像頭,你想要連上攝像頭的Wi-Fi熱點(diǎn)去配置這個(gè)攝像頭的話,以前要這么操作:

現(xiàn)在用NEHotSpotConfiguration就能很方便地搞定事情了:

當(dāng)然,這套API也可以被拿來模擬各種網(wǎng)絡(luò)環(huán)境,在測(cè)試App的時(shí)候很有用。

(2)NEDNSProxyProvider

NEDNSProxyProvider可以用來設(shè)置你的手機(jī)如何跟DNS做交互。你可以自己發(fā)DNS請(qǐng)求,也可以自己基于不同的協(xié)議去做DNS查詢。例如DNS over TLS,DNS over HTTP。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容