本文基于okhttp的wiki翻譯而來,根據(jù)自己的理解對文檔進行了通俗易懂的翻譯,如有錯誤還請指正早敬。
1趁耗、okhttp的相關(guān)概念
1.1沉唠、Calls
Requests(請求)
每個http的請求包含一個url、一個method(請求方法苛败,例如get满葛、post)、請求頭部(headers)罢屈,可能也包含一個請求體(body:具有明確數(shù)據(jù)類型的數(shù)據(jù)流)嘀韧。
Responses(響應(yīng))
對于某個請求的響應(yīng)往往包含一個響應(yīng)碼(code,如成功返回200缠捌,為找到資源返回404)锄贷、響應(yīng)頭部(headers)、和一個響應(yīng)體(body)曼月。
Rewriting Requests(重寫請求)
為了保證一個http請求的正確性和高效性谊却,okhttp往往在發(fā)起網(wǎng)絡(luò)請求之前會重寫你的請求信息。
有些請求頭信息如果在你提交的原始請求里面不存在哑芹,okhttp會幫你去添加這些請求頭炎辨。這些請求頭包含Content-Length、Transfer-Encoding聪姿、User-Agent碴萧、Host、Connection和Content-Type咳燕。如果你沒有添加Accept-Encoding請求頭的話勿决,okhttp會添加一個Accept-Encoding請求頭來保證對響應(yīng)(response)進行一個透明壓縮。如果你有使用cookies招盲,okhttp同樣會添加一個cookie請求頭低缩。
一些網(wǎng)絡(luò)請求可能會通過緩存來獲取數(shù)據(jù)。當(dāng)這個緩存數(shù)據(jù)過期了的話曹货,okhttp會去服務(wù)端獲取相應(yīng)信息并更新緩存咆繁,為了使用緩存,你需要添加If-Modified-Since和If-None-Match請求頭顶籽。
Rewriting Responses(重寫響應(yīng))
如果響應(yīng)使用了透明壓縮玩般,okhttp會丟棄原有的Content-Encoding和Content-Length請求頭,因為他們和解壓后的請求體是不匹配的礼饱。
如果get條件請求成功了坏为,網(wǎng)絡(luò)響應(yīng)和緩存響應(yīng)將按照一定規(guī)格進行合并究驴。
Follow-up Requests(請求追蹤)
當(dāng)你請求的url轉(zhuǎn)移到其他地方,請求服務(wù)會返回一個302的狀態(tài)碼并指示一個新的url地址匀伏,okhttp會對這個url進行重定向直到獲取到最終的請求地址洒忧。
如果服務(wù)器需要客戶端進行一個授權(quán)驗證,okhttp將尋求Authenticator(如果設(shè)置了的話)來提交授權(quán)驗證够颠,如果Authenticator提供了授權(quán)憑證熙侍,okhttp將使用該憑證再次發(fā)起請求。
Retrying Requests(失敗重連)
有些時候網(wǎng)絡(luò)請求可能會失敗履磨,這可能是因為連接池地址已經(jīng)失效導(dǎo)致不能連接蛉抓,又或者是服務(wù)器異常無法訪問。這種情況下okhttp將會試圖通過其他可用的router(路由)來重新發(fā)起連接請求剃诅。
Calls
由于okhttp的重寫(reWriting)巷送、追蹤(follow up)、重定向(redirects)和重連(retries)機制综苔,一個簡單的網(wǎng)絡(luò)請求可能會產(chǎn)生多個請求和響應(yīng)惩系。即使中間包含多個必要的請求和相應(yīng),okhttp都能通過call來模擬任務(wù)從而滿足你發(fā)起的網(wǎng)絡(luò)請求如筛。通常這不是很多!但是抒抬,如果您的URL被重定向或者故障轉(zhuǎn)移到備用IP地址杨刨,您的代碼將繼續(xù)有效,這一點令人欣慰擦剑。
call執(zhí)行的兩種方式:
同步執(zhí)行(Synchronous):在獲取到響應(yīng)之前會阻塞當(dāng)前線程妖胀。
異步執(zhí)行(Asynchronous):在某個線程中執(zhí)行請求,在另一個線程獲取返回值(call back)惠勒。
calls可以被取消(canceled),當(dāng)取消一個未完成的請求時赚抡,請求會失敗并且拋出一個IoException。
Dispatcher
對于同步請求纠屋,你需要自己創(chuàng)建線程來管理多個并發(fā)的請求涂臣,并發(fā)請求數(shù)太多會造成資源的浪費,太少又會造成相應(yīng)延遲售担。
對于異步請求赁遗,Dispatcher有一個最大同時請求數(shù)的策略。您可以設(shè)置每個網(wǎng)絡(luò)服務(wù)器的最大值(默認值為5)和總體(默認值為64)族铆。
1.2岩四、Connections
即使你僅僅提供了一個url地址,okhttp計劃使用三種類型來連接到你的服務(wù)器:Url哥攘、Address剖煌、Route材鹦。
URLs
URLs(如https://github.com/square/okhttp)是http和Internet的基礎(chǔ)。除了為web上所有資源提供分散的命名之外耕姊,他還能指定如何獲取web上的資源侠姑。
URLs是一個抽象的概念(abstract):
- 它指定了一個call是明文的http請求還是加密的https請求,但它并沒有指定通過哪種加密算法進行數(shù)據(jù)加密箩做,沒有指定該怎樣去證實一個正數(shù)的有效性(HostNameVerifier)莽红,也沒有指定那些證書應(yīng)該被信任(SSLSocketFactory)。
- 它沒有指定是否應(yīng)該使用特定的代理服務(wù)器或者如何使用該代理服務(wù)器進行身份驗證邦邦。
同時URLs也是一個實在的概念:每個URL都有確定路徑(如/square/okhttp)安吁,和請求參數(shù)(如?q=sharks&lang=en)。每個服務(wù)器擁有多個URLs燃辖。
Address
Address指定了一個服務(wù)器(如github.com)和連接到這個服務(wù)器所需要的所有靜態(tài)配置:端口號鬼店、https的一些設(shè)置和首選的網(wǎng)絡(luò)協(xié)議(如http2.0或者spdy協(xié)議)。
具有相同地址(Address)的URLs通常會共用同一個TCP的socket連接黔龟。共用同一個socket連接有非常不錯的表現(xiàn)力:低延遲妇智、高吞吐量和低耗電。okhttp通過連接池來自動重用http1.x氏身,http2.0和SPDY的連接巍棱。
在OKhttp中,地址的設(shè)置一部分來源于URL(scheme蛋欣、hostname航徙、port),一部分來源于OKhttpClient。
Routes
Routes提供實際連接到服務(wù)器所需的動態(tài)信息陷虎。它提供一個明確的IP地址(由DNS查詢找到)到踏,確切的代理服務(wù)器(如果ProxySelector是有用的話),以及要協(xié)商的TSL版本(針對https連接)尚猿。
對于單一的地址可能有許多的路由窝稿,例如一個擁有多個數(shù)據(jù)中心的服務(wù)器可能會產(chǎn)生多個IP地址在他的DNS響應(yīng)當(dāng)中。
Connections
當(dāng)你使用okhttp去請求一個url凿掂,OKhttp為我們做了以下事情:
1伴榔、使用這個url和已配置好的okhttpClient去創(chuàng)建一個地址(Address),這個地址聲明了我們將如何連接到服務(wù)器缠劝。
2潮梯、通過這個地址(Address)在連接池(connection pool)中嘗試獲得一個連接。
3惨恭、如果在連接池中沒有找到一個有效的連接秉馏,okhttp將嘗試使用路由(route)。這意味著需要發(fā)起一個DNS請求來獲取服務(wù)器的IP地址脱羡,接著選擇一個TSL版本和代理服務(wù)器萝究。
4免都、如果是一個新的路由,連接的建立要么通過一個直接的socket連接和一個TSL通道帆竹,要么通過直接使用一個TSL連接绕娘。必要時需要三次握手。
5栽连、發(fā)送request請求然后獲取reponse響應(yīng)险领。
如果當(dāng)前連接遇到了問題,okhttp會選擇另外一個路由再次嘗試秒紧。這使得當(dāng)一個服務(wù)器地址是無法訪問的時候绢陌,okhttp也能夠恢復(fù)連接。同樣熔恢,當(dāng)連接池過期或者試圖使用一個不支持的TSL版本脐湾,okhttp仍然能夠恢復(fù)有效的連接。
一旦獲取到了服務(wù)器響應(yīng)(response)叙淌,當(dāng)前連接將被存放到連接池中以便再次請求的時候可以重用它秤掌。當(dāng)連接在一段時間沒有使用時將會移除連接池。