很多時候,AFNetworking都是目前iOS
開發(fā)者網(wǎng)絡(luò)庫中的不二選擇。Github
上2W+
的star
數(shù)足見其流行程度。而從iOS7.0
開始,蘋果推出了新的網(wǎng)絡(luò)庫繼承者NSURLSession
后,AFNetworking
也毫不猶豫地加入了對其的支持。3.0+
更加只是提供了NSURLSession
的支持。
我們使用AFNetworking
的時候,可能會有很多的朋友都會采用以下的寫法:
AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];
sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
[sessionManager GET:urlString
parameters:parameters
progress:progressBlock
success:successHandler
failure:failureHandler];
大概可以描述一下這個過程,每次開啟一個網(wǎng)絡(luò)請求時,首先新建一個AFHTTPSessionManager
,然后將相關(guān)的requestSerializer
和reponseSerializer
賦值;最后發(fā)起相應(yīng)的GET/POST
等請求。
而如果是直接采用NSURLSession
來請求網(wǎng)絡(luò)呢,我們則經(jīng)常會采用以下的寫法:
NSURLSession *session = [NSURLSession
sessionWithConfiguration:
[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:completionHandler];
[dataTask resume];
這個過程其實(shí)和上面的基本一致。新建一個Session
,然后新建task
,激活task
,完成網(wǎng)絡(luò)請求。
那么現(xiàn)在問題來了。為什么每次都需要新建一個SessionManager/Session
?如果在多個Task
請求的情況下,如果采取一個共享的SessionManager/Session
是否可行?如果可行,與之前每次新建SessionManager/Session
相比,孰優(yōu)孰劣?
本篇文章會告訴您:
??1. 為什么要使用NSURLSession而不是NSURLConnection
??2. 為什么要用共享的SessionManager/Session
,而不是每次都啟動一個新的
為什么要選擇NSURLSession
NSURLSession
在iOS7.0
時被Apple提出后,雖然Apple一直對其良好的API
設(shè)計(jì)大力推廣,然而其能夠達(dá)到的效果,似乎一直都和NSURLConnection
不相伯仲。
特別是在網(wǎng)絡(luò)的Dependecy
依賴處理上,由于AFNetworking
優(yōu)秀的架構(gòu)設(shè)計(jì),NSURLSession
甚至還不如NSURLConnection
好用。那么,有什么理由切換到NSURLSession
? 2015年的WWDC似乎告訴了我們答案。
HTTP /2
, 2015年5月RFC 7540正式發(fā)表的下一代HTTP協(xié)議,是1999年來HTTP 1.1
發(fā)布后的首個更新。相對于前一個版本,HTTP /2
以快
著稱。如下圖,對相同圖片、相同服務(wù)器的下載,在不同協(xié)議下所需的時間:
這里我們并不打算展開HTTP /2
的原理,有興趣的同學(xué)可以Google之。根據(jù)2015的WWDC Session711,我們知道iOS9+
,NSURLSession
開始正式支持HTTP /2
,也就意味著你的網(wǎng)絡(luò)連接速度也可以有如上圖那樣的提升。
更人性化更優(yōu)秀的API
設(shè)計(jì),HTTP /2
的支持,這是否能成為你使用NSURLSession
的理由?至少它們成為了說服我的理由。
為什么要盡量共享Session,而不是每次新建Session
在回答這個問題以前,我們先來聊聊網(wǎng)絡(luò)的通訊協(xié)議。我們也都知道,HTTP
協(xié)議是基于TCP
協(xié)議的。所以在每次的HTTP
請求之前,客戶端和服務(wù)器端,都先需要經(jīng)過TCP
連接的三次握手,即每次請求之前,網(wǎng)絡(luò)的數(shù)據(jù)都已經(jīng)在客戶端和服務(wù)器端之間來回了三次。如下圖:
事實(shí)上在HTTP 0.9
, HTTP 1.0
協(xié)議的時代,每次HTTP的請求,都需要先經(jīng)過TCP
的連接,然后才開始HTTP
的請求,這樣一個流程圖,我們可以通過抓包看到:
那么,為了讓我們的請求更快,避免每次都產(chǎn)生一個TCP
三次握手,成了一個優(yōu)化的選項(xiàng)。于是在HTTP 1.1
中,出現(xiàn)了Connection: keep-alive
?這個選項(xiàng)。這個優(yōu)化選項(xiàng),可以使得客戶端和服務(wù)器端復(fù)用一個TCP
連接,從而減小每次的網(wǎng)絡(luò)請求時間。
聊到這里,本章提出的問題,其實(shí)答案已經(jīng)逐漸明了了。沒錯,共享的Session
將會復(fù)用TCP
的連接,而每次都新建Session
的操作將導(dǎo)致每次的網(wǎng)絡(luò)請求都開啟一個TCP
的三次握手。
從上面兩張圖,我們可以清晰地看到,同樣都是兩次HTTP請求,共享Session
的代碼在第二次網(wǎng)絡(luò)請求時少了TCP
的三次握手的過程。即加速了整個網(wǎng)絡(luò)的請求時間。
事實(shí)上,蘋果的文檔中,還對一個服務(wù)器最高的TCP
并發(fā)有相應(yīng)的描述:
HTTPMaximumConnectionsPerHost Property
The maximum number of simultaneous connections to make to a given host.
Declaration
SWIFT
var HTTPMaximumConnectionsPerHost: Int
OBJECTIVE-C
@property NSInteger HTTPMaximumConnectionsPerHost
Discussion
This property determines the maximum number of simultaneous connections made to each host by tasks within sessions based on this configuration.
This limit is per session, so if you use multiple sessions, your app as a whole may exceed this limit. Additionally, depending on your connection to the Internet, a session may use a lower limit than the one you specify.
The default value is 6 in OS X, or 4 in iOS.
Availability
Available in iOS 7.0 and later.
我們可以看到,默認(rèn)配置下,iOS
對于同一個IP服務(wù)器的并發(fā)最大為4
,OS X
為6
。而如果你沒有使用共享的Session
,則可能會超過這個數(shù)。
因此,如果能用共享的Session
,還是用共享的吧。有些許的網(wǎng)絡(luò)加速,也是一件不錯的事情,您說呢?
結(jié)語
To be, or not to be, that is the question.
雖然只是一個簡單的東西,卻也有大文章。
本文歡迎轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)還請注明作者和出處。謝謝!