1、前言
網絡通信一直是Android項目里比較重要的一個模塊统舀,Android開源項目上出現(xiàn)過很多優(yōu)秀的網絡框架,從一開始只是一些對HttpClient和HttpUrlConnection簡易封裝使用的工具類奋蔚,到后來Google開源的比較完善豐富的Volley送火,再到如今比較流行的Okhttp、Retrofit歹茶。
要想理解他們之間存在的異同(或者具體點說夕玩,要想更深入地掌握Android開發(fā)中的網絡通信技術)你弦,必須對網絡基礎知識、Android網絡框架的基本原理等做到心中有數(shù)燎孟、信手拈來禽作,關鍵時刻才能找到適合您APP的最佳網絡通信技術實踐。
事實證明在Android的日常開發(fā)和源碼閱讀中也會經常碰到相關知識揩页,掌握這些網絡基礎知識旷偿,也是Android程序員真正邁向高階的過程中必備的一些基本技術素質之一。
有鑒于此爆侣,本文將主要介紹計算機網絡的一些基礎萍程,以及在Android開發(fā)中的一些使用及遇到的問題和解決。
本篇主要分為以下幾部分:
1)計算機網絡體系結構累提;
2)Http相關尘喝;
3)Tcp相關;
4)Socket斋陪。
學習交流:
- 即時通訊開發(fā)交流3群:185926912[推薦]
- 移動端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動端IM》
(本文同步發(fā)布于:http://www.52im.net/thread-1963-1-1.html)
2朽褪、關于作者
舒大飛:攜程網Android開發(fā)工程師,作者博客:http://www.reibang.com/u/ae379336190b无虚。
注:在收錄本文時缔赠,為了更易于理解,對內容做了更為細致的修訂友题。
3嗤堰、計算機網絡體系結構
計算機網絡體系結構,即經扯然拢看到的計算機網絡體系的分層結構踢匣,理清這個還是有必要的,防止對Http和Tcp兩個根本不在同一層的協(xié)議糾纏不清戈抄。 根據(jù)不同的參考模型离唬,分層結構有幾個不同的版本,如OSI模型以及TCP/IP模型划鸽。
下面就以比較經呈漭海看到的的5層結構為例:
(更為清晰完整的圖,請見《計算機網絡通訊協(xié)議關系圖(中文珍藏版)[附件下載] 》)
如上圖所示裸诽,五層的體系結構至上往下嫂用,最終可以實現(xiàn)端對端之間的數(shù)據(jù)傳輸與通信,他們各自負責一些什么丈冬,最終如何實現(xiàn)端對端之間的通信嘱函?
1)應用層:如http協(xié)議,它實際上是定義了如何包裝和解析數(shù)據(jù)埂蕊,應用層是http協(xié)議的話往弓,則會按照協(xié)議規(guī)定包裝數(shù)據(jù)橄浓,如按照請求行、請求頭亮航、請求體包裝,包裝好數(shù)據(jù)后將數(shù)據(jù)傳至運輸層匀们。
2)運輸層:運輸層有TCP和UDP兩種協(xié)議缴淋,分別對應可靠的運輸和不可靠的運輸,如TCP因為要提供可靠的傳輸泄朴,所以內部要解決如何建立連接重抖、如何保證傳輸是可靠的不丟數(shù)據(jù)、如何調節(jié)流量控制和擁塞控制祖灰。關于這一層钟沛,我們平常一般都是和Socket打交道,Socket是一組封裝的編程調用接口局扶,通過它恨统,我們就能操作TCP、UDP進行連接的建立等三妈。我們平常使用Socket進行連接建立的時候畜埋,一般都要指定端口號,所以這一層指定了把數(shù)據(jù)送到對應的端口號。
3)網絡層:這一層IP協(xié)議畴蒲,以及一些路由選擇協(xié)議等等悠鞍,所以這一層的指定了數(shù)據(jù)要傳輸?shù)侥膫€IP地址。中間涉及到一些最優(yōu)線路模燥,路由選擇算法等等咖祭。
4)數(shù)據(jù)鏈路層:印象比較深的就是ARP協(xié)議,負責把IP地址解析為MAC地址蔫骂,即硬件地址么翰,這樣就找到了對應的唯一的機器。
5)物理層:這一層就是最底層了纠吴,提供二進制流傳輸服務硬鞍,也就是也就是真正開始通過傳輸介質(有線、無線)開始進行數(shù)據(jù)的傳輸了戴已。
所以通過上面五層的各司其職固该,實現(xiàn)物理傳輸介質--MAC地址--IP地址--端口號--獲取到數(shù)據(jù)根據(jù)應用層協(xié)議解析數(shù)據(jù)最終實現(xiàn)了網絡通信和數(shù)據(jù)傳輸。
下面會著重講一下HTTP和TCP相關的東西糖儡,關于其他層伐坏,畢業(yè)了這么久也忘的很多,如果想更加細致具體的了解像下面三層的如路由選擇算法握联、ARP尋址以及物理層等等還是要重新去看一下《TCP/IP詳解 卷1:協(xié)議》~
4桦沉、HTTP相關
本節(jié)主要講一些關于Http的基礎知識,以及在Android中的一些實際應用和碰到的問題和解決纯露。
限于篇幅原因剿骨,本文在一些知識點上只做簡要性的概述,如果想要全面深入地掌握HTTP協(xié)議埠褪,請閱讀以下文章:
《網絡編程懶人入門(七):深入淺出浓利,全面理解HTTP協(xié)議》
《從HTTP/0.9到HTTP/2:一文讀懂HTTP協(xié)議的歷史演變和設計思路》
《腦殘式網絡編程入門(三):HTTP協(xié)議必知必會的一些知識》
4.1 正確理解HTTP的“無連接”“與無狀態(tài)”
Http是無連接無狀態(tài)的。
無連接并不是說不需要連接钞速,Http協(xié)議只是一個應用層協(xié)議贷掖,最終還是要靠運輸層的如TCP協(xié)議向上提供的服務進行連接。
無連接的含義是http約定了每次連接只處理一個請求渴语,一次請求完成后就斷開連接苹威,這樣主要是為了緩解服務器的壓力,減小連接對服務器資源的占用驾凶。我的理解是牙甫,建立連接實際上是運輸層的事,面向應用層的http來說的話调违,它就是無連接的腹暖,因為上層對下層無感知。
無狀態(tài)的指每個請求之間都是獨立的翰萨,對于之前的請求事務沒有記憶的能力脏答。所以就出現(xiàn)了像Cookie這種,用來保存一些狀態(tài)的東西亩鬼。
4.2 請求報文與響應報文
這里主要簡單說一下HTTP請求報文和響應報文的格式方面的基礎知識殖告。
請求報文:
響應報文:
關于Get和Post,我們都熟知的關于Get和Post的區(qū)別大致有以下幾點:
1)Get會把請求參數(shù)都拼接在url后面雳锋,最終顯示在地址欄黄绩,而Post則會把請求參數(shù)數(shù)據(jù)放進請求體中,不會再地址欄顯示出來玷过;
2)傳遞參數(shù)的長度限制爽丹。
問題:
對于第1)點,如果是在瀏覽器里把隱私數(shù)據(jù)暴露在地址欄上確實不妥辛蚊,但是如果是在App開發(fā)中呢粤蝎,沒有地址欄的概念,那么這一點是不是還會成為選擇post還是get的制約條件袋马;
對于第2)點初澎,長度的限制應該是瀏覽器的限制,跟get本身無關虑凛,如果是在App開發(fā)中碑宴,這一點是否也可以忽略软啼。
4.3 HTTP的緩存機制
之所以想介紹以下Http的緩存機制,是因為Okhttp中對于網絡請求緩存這一塊就是利用了Http的的緩存機制延柠,而不是像Volley等框架那樣客戶端完全自己寫一套緩存策略自己玩祸挪。
Http的緩存主要利用header里的兩個字段來控制:即Cache-control和ETag,下面將分別來介紹贞间。
1)Cache-control主要包含以及幾個字段:
private:則只有客戶端可以緩存匕积;
public:客戶端和代理服務器都可以緩存;
max-age:緩存的過期時間榜跌;
no-cache:需要使用對比緩存來驗證緩存數(shù)據(jù);
no-store:所有內存都不會進行緩存盅粪。
實際上就是在這里面設置了一個緩存策略钓葫,由服務端第一次通過header下發(fā)給客戶端,可以看到:
max-age:即緩存過期的時間票顾,則之后再次請求础浮,如果沒有超過緩存失效的時間則可以直接使用緩存;
no-cache:表示需要使用對比緩存來驗證緩存數(shù)據(jù)奠骄,如果這個字段是打開的豆同,則就算max-age緩存沒有失效,則還是需要發(fā)起一次請求向服務端確認一下資源是否有更新含鳞,是否需要重新請求數(shù)據(jù)影锈,至于怎么做對比緩存,就是下面要說的Etag的作用蝉绷。如果服務端確認資源沒有更新鸭廷,則返回304,取本地緩存即可熔吗,如果有更新辆床,則返回最新的資源;
no-store:這個字段打開桅狠,則不會進行緩存讼载,也不會取緩存。
2)ETag:即用來進行對比緩存中跌,Etag是服務端資源的一個標識碼
當客戶端發(fā)送第一次請求時服務端會下發(fā)當前請求資源的標識碼Etag咨堤,下次再請求時,客戶端則會通過header里的If-None-Match將這個標識碼Etag帶上漩符,服務端將客戶端傳來的Etag與最新的資源Etag做對比吱型,如果一樣,則表示資源沒有更新陨仅,返回304津滞。
3)小結:
通過Cache-control和Etag的配合來實現(xiàn)Http的緩存機制铝侵。更多有關HTTP緩存方面的的知識,在文章《腦殘式網絡編程入門(三):HTTP協(xié)議必知必會的一些知識》的相關章節(jié)做了詳細的讀解触徐,可以參閱之咪鲜。
4.4 HTTP的Cookie
上面說了Http協(xié)議是無狀態(tài)的,而Cookie就是用來在本地緩存記住一些狀態(tài)的撞鹉,一個Cookie一般都包含domin(所屬域)疟丙、path、Expires(過期時間)等幾個屬性鸟雏。服務端可以通過在響應頭里的set-cookies來將狀態(tài)寫入客戶端的Cookie里享郊。下次客戶端發(fā)起請求時可以將Cookie帶上。
Android開發(fā)中遇到的問題及解決:
說起Cookie孝鹊,一般如果平常只是做App開發(fā)猎醇,比較不經常遇到宗苍,但是如果是涉及到WebView的需求呢簸,則有可能會遇到搀突。
下面就說一下我在項目里遇到過的一個關于WebView Cookie的揪心往事:需求是這樣的,加載的WebView中的H5頁面需要是已登錄狀態(tài)的柳骄,所以我們需要在原生頁面登錄后团赏,手動將ticket寫入WebView的Cookie,之后WebView里加載的H5頁面帶著Cookie里的ticket給服務端驗證通過就好了耐薯。
但是遇到一個問題:通過Chrome inspect調試WebView舔清,手動寫的Cookie確實是已經寫進去了,但是發(fā)起請求的時候曲初,Cookie就是沒有帶上鸠踪,導致請求驗證失敗,之后通過排查复斥,是WebView的屬性默認關閉引起营密,通過下面的代碼設置打開即可:
CookieManager cookieManager = CookieManager.getInstance();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.setAcceptThirdPartyCookies(mWebView, true);
} else{
cookieManager.setAcceptCookie(true);
}
4.5 Https
我們都知道Https保證了我們數(shù)據(jù)傳輸?shù)陌踩琀ttps=Http+Ssl目锭,之所以能保證安全主要的原理就是利用了非對稱加密算法评汰,平常用的對稱加密算法之所以不安全,是因為雙方是用統(tǒng)一的密匙進行加密解密的痢虹,只要雙方任意一方泄漏了密匙被去,那么其他人就可以利用密匙解密數(shù)據(jù)。
而非對稱加密算法之所以能實現(xiàn)安全傳輸?shù)暮诵木A就是:公鑰加密的信息只能用私鑰解開奖唯,私鑰加密的信息只能被公鑰解開惨缆。
1)簡述非對稱加密算法為什么安全:
服務端申請CA機構頒發(fā)的證書,則獲取到了證書的公鑰和私鑰,私鑰只有服務器端自己知道坯墨,而公鑰可以告知其他人寂汇,如可以把公鑰傳給客戶端,這樣客戶端通過服務端傳來的公鑰來加密自己傳輸?shù)臄?shù)據(jù)捣染,而服務端利用私鑰就可以解密這個數(shù)據(jù)了骄瓣。由于客戶端這個用公鑰加密的數(shù)據(jù)只有私鑰能解密,而這個私鑰只有服務端有耍攘,所以數(shù)據(jù)傳輸就安全了榕栏。
上面只是簡單說了一下非對稱加密算法是如何保證數(shù)據(jù)安全的,實際上Https的工作過程遠比這要復雜(篇幅限制這里就不細說了蕾各,網上有很多相關文章):
一個是客戶端還需要驗證服務端傳來的CA證書的合法性扒磁、有效性,因為存在傳輸過程CA證書被人調包的風險,涉及到客戶端如何驗證服務器證書的合法性的問題式曲,保證通信雙方的身份合法妨托;
另一個是非對稱算法雖然保證了數(shù)據(jù)的安全,但是效率相對于對稱算法來說比較差检访,如何來優(yōu)化,實現(xiàn)既保證了數(shù)據(jù)的安全仔掸,又提高了效率脆贵。
2)客戶端如何驗證證書的合法性:
首先CA證書一般包括以下內容:
證書的頒發(fā)機構以及版本;
證書的使用者起暮;
證書的公鑰卖氨;
證書有效時間;
證書的數(shù)字簽名Hash值以及簽名Hash算法(這個數(shù)字簽名Hash值是用證書的私鑰加密過的值)负懦;
等等筒捺。
客戶端驗證服務端傳過來的證書的合法性是通過:先利用獲取到的公鑰來解密證書中的數(shù)字簽名Hash值1(因為它是利用私鑰加密的嘛),然后在利用證書里的簽名Hash算法生成一個Hash值2纸厉,如果兩個值相等系吭,則表示證書合法,服務器端可以被信任颗品。
3)Android開發(fā)中遇到的問題及解決:
順便說一個在項目開發(fā)中使用Android WebView加載公司測試服務器上網頁證書過期導致網頁加載不出來白屏的問題肯尺。
解決方案就是測試環(huán)境下暫時忽略SSL的報錯,這樣就可以把網頁加載出來躯枢,當然在生產上不要這么做则吟,一個是會有安全問題,一個是google play應該審核也不會通過锄蹂。
最佳辦法是重寫WebViewClient的onReceivedSslError():
@Override
publicvoidonReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if(ContextHolder.sDebug) {
handler.proceed();
return;
}
super.onReceivedSslError(view, handler, error);
}
最后:有關HTTPS更為詳細全面的知識氓仲,請深入閱讀《即時通訊安全篇(七):如果這樣來理解HTTPS原理,一篇就夠了》。
4.6 Http 2.0
Okhttp支持配置使用Http 2.0協(xié)議敬扛,Http2.0相對于Http1.x來說提升是巨大的晰洒,主要有以下幾點。
1)二進制格式:http1.x是文本協(xié)議舔哪,而http2.0是二進制以幀為基本單位欢顷,是一個二進制協(xié)議,一幀中除了包含數(shù)據(jù)外同時還包含該幀的標識:Stream Identifier捉蚤,即標識了該幀屬于哪個request,使得網絡傳輸變得十分靈活抬驴;
2)多路復用:一個很大的改進,原先http1.x一個連接一個請求的情況有比較大的局限性缆巧,也引發(fā)了很多問題布持,如建立多個連接的消耗以及效率問題。
http1.x為了解決效率問題陕悬,可能會盡量多的發(fā)起并發(fā)的請求去加載資源题暖,然而瀏覽器對于同一域名下的并發(fā)請求有限制,而優(yōu)化的手段一般是將請求的資源放到不同的域名下來突破這種限制捉超。
而http2.0支持的多路復用可以很好的解決這個問題胧卤,多個請求共用一個TCP連接,多個請求可以同時在這個TCP連接上并發(fā)拼岳,一個是解決了建立多個TCP連接的消耗問題枝誊,一個也解決了效率的問題。
那么是什么原理支撐多個請求可以在一個TCP連接上并發(fā)呢惜纸?基本原理就是上面的二進制分幀叶撒,因為每一幀都有一個身份標識,所以多個請求的不同幀可以并發(fā)的無序發(fā)送出去耐版,在服務端會根據(jù)每一幀的身份標識祠够,將其整理到對應的request中。
3)header頭部壓縮:主要是通過壓縮header來減少請求的大小粪牲,減少流量消耗古瓤,提高效率。因為之前存在一個問題是腺阳,每次請求都要帶上header湿滓,而這個header中的數(shù)據(jù)通常是一層不變的。
4)支持服務端推送舌狗。
有關HTTP2的更多知識叽奥,請閱讀《從HTTP/0.9到HTTP/2:一文讀懂HTTP協(xié)議的歷史演變和設計思路》。
5痛侍、TCP相關
TCP面向連接朝氓,提供可靠的數(shù)據(jù)傳輸魔市。在這一層,我們通常都是通過Socket Api來操作TCP赵哲,建立連接等等待德。
5.1 三次握手建立連接
第一次:發(fā)送SNY=1表示此次握手是請求建立連接的,然后seq生成一個客戶端的隨機數(shù)X
第二次:發(fā)送SNY=1,ACK=1表示是回復請求建立連接的枫夺,然后ack=客戶端的seq+1(這樣客戶端收到后就能確認是之前想要連接的那個服務端)将宪,然后把服務端也生成一個代表自己的隨機數(shù)seq=Y發(fā)給客戶端。
第三次:ACK=1橡庞。 seq=客戶端隨機數(shù)+1较坛,ack=服務端隨機數(shù)+1(這樣服務端就知道是剛剛那個客戶端了)
為什么建立連接需要三次握手?
首先非常明確的是兩次握手是最基本的扒最,第一次握手丑勤,C端發(fā)了個連接請求消息到S端,S端收到后S端就知道自己與C端是可以連接成功的吧趣,但是C端此時并不知道S端是否接收到這個消息法竞,所以S端接收到消息后得應答,C端得到S端的回復后强挫,才能確定自己與S端是可以連接上的岔霸,這就是第二次握手。
C端只有確定了自己能與S端連接上才能開始發(fā)數(shù)據(jù)俯渤。所以兩次握手肯定是最基本的呆细。
那么為什么需要第三次握手呢?假設一下如果沒有第三次握手稠诲,而是兩次握手后我們就認為連接建立侦鹏,那么會發(fā)生什么诡曙?
第三次握手是為了防止已經失效的連接請求報文段突然又傳到服務端臀叙,因而產生錯誤。
具體情況就是:
C端發(fā)出去的第一個網絡連接請求由于某些原因在網絡節(jié)點中滯留了价卤,導致延遲劝萤,直到連接釋放的某個時間點才到達S端,這是一個早已失效的報文慎璧,但是此時S端仍然認為這是C端的建立連接請求第一次握手床嫌,于是S端回應了C端,第二次握手胸私。
如果只有兩次握手厌处,那么到這里,連接就建立了岁疼,但是此時C端并沒有任何數(shù)據(jù)要發(fā)送阔涉,而S端就會傻傻的等待著,造成很大的資源浪費。所以需要第三次握手瑰排,只有C端再次回應一下贯要,就可以避免這種情況。
要想深刻理解TCP三次握手椭住,請不要錯過以下文章:
《理論經典:TCP協(xié)議的3次握手與4次揮手過程詳解》
《理論聯(lián)系實際:Wireshark抓包分析TCP 3次握手崇渗、4次揮手過程》
《腦殘式網絡編程入門(一):跟著動畫來學TCP三次握手和四次揮手》
5.2 四次揮手斷開連接
經過上面的建立連接圖的解析,這個圖應該不難看懂京郑。
這里主要有一個問題:為什么比建立連接時多了一次揮手宅广?
可以看到這里服務端的ACK(回復客戶端)和FIN(終止)消息并不是同時發(fā)出的,而是先ACK傻挂,然后再FIN乘碑,這也很好理解,當客戶端要求斷開連接時金拒,此時服務端可能還有未發(fā)送完的數(shù)據(jù)兽肤,所以先ACK,然后等數(shù)據(jù)發(fā)送完再FIN绪抛。這樣就變成了四次握手了资铡。
上面講了TCP建立連接和斷開連接的過程,TCP最主要的特點就是提供可靠的傳輸幢码,那么他是如何保證數(shù)據(jù)傳輸是可靠的呢笤休,這就是下面要講的滑動窗口協(xié)議。
相關知識請深入閱讀:
《理論經典:TCP協(xié)議的3次握手與4次揮手過程詳解》
《理論聯(lián)系實際:Wireshark抓包分析TCP 3次握手症副、4次揮手過程》
《腦殘式網絡編程入門(一):跟著動畫來學TCP三次握手和四次揮手》
5.3 滑動窗口協(xié)議
滑動窗口協(xié)議是保證TCP的可靠傳輸?shù)母镜暄牛驗榘l(fā)送窗口只有收到確認幀才會向后移動窗口繼續(xù)發(fā)送其他幀。
下面舉個例子:假如發(fā)送窗口是3幀
一開始發(fā)送窗口在前3幀[1,2,3],則前3幀是可以發(fā)送的贞铣,后面的則暫時不可以發(fā)送闹啦,比如[1]幀發(fā)送出去后,收到了來自接收方的確認消息辕坝,則此時發(fā)送窗口才可以往后移1幀窍奋,發(fā)送窗口來到[2,3酱畅,4]琳袄,同樣只有發(fā)送窗口內的幀才可以被發(fā)送,一次類推纺酸。
而接收窗口接收到幀后將其放入對應的位置窖逗,然后移動接收窗口,接口窗口與發(fā)送窗口一樣也有一個大小餐蔬,如接收窗口是5幀碎紊,則落在接收窗口之外的幀會被丟棄在张。
發(fā)送窗口和接收窗口大小的不同設定就延伸出了不同的協(xié)議:
停止-等待協(xié)議:每發(fā)一幀都要等到確認消息才能發(fā)送下一幀,缺點:效率較差矮慕。
后退N幀協(xié)議:采取累計確認的方式帮匾,接收方正確的接受到N幀后發(fā)一個累計確認消息給發(fā)送窗口,確認N幀已正確收到痴鳄,如果發(fā)送方規(guī)定時間內未收到確認消息則認為超時或數(shù)據(jù)丟失瘟斜,則會重新發(fā)送確認幀之后的所有幀。缺點:出錯序號后面的PDU已經發(fā)送過了痪寻,但是還是要重新發(fā)送螺句,比較浪費。
選擇重傳協(xié)議:若出現(xiàn)差錯橡类,只重新傳輸出現(xiàn)差錯涉及需要的PDU,提高了傳輸效率蛇尚,減少不必要的重傳。
到這里還剩下最后一個問題:由于發(fā)送窗口與接收窗口之間會存在發(fā)送效率和接收效率不匹配的問題顾画,就會導致?lián)砣〗伲鉀Q這個問題TCP有一套流量控制和擁塞控制的機制。
5.4 流量控制和擁塞控制
1)流量控制:
流量控制是對一條通信路徑上的流量進行控制研侣,就是發(fā)送方通過獲取接收方的回饋來動態(tài)調整發(fā)送的速率谱邪,來達到控制流量的效果,其目的是保證發(fā)送者的發(fā)送速度不超過接收者的接收速度庶诡。
2)擁塞控制:
擁塞控制是對整個通信子網的流量進行控制惦银,屬于全局控制。
① 慢開始+擁塞避免
先來看一張經典的圖:
一開始使用慢啟動末誓,即擁塞窗口設為1扯俱,然后擁塞窗口指數(shù)增長到慢開始的門限值(ssthresh=16),則切換為擁塞避免,即加法增長,這樣增長到一定程度喇澡,導致網絡擁塞迅栅,則此時會把擁塞窗口重新降為1,即重新慢開始撩幽,同時調整新的慢開始門限值為12库继,之后以此類推箩艺。
② 快重傳+快恢復
快重傳:上面我們說的重傳機制都是等到超時還未收到接收方的回復窜醉,才開始進行重傳。而快重傳的設計思路是:如果發(fā)送方收到3個重復的接收方的ACK艺谆,就可以判斷有報文段丟失榨惰,此時就可以立即重傳丟失的報文段,而不用等到設置的超時時間到了才開始重傳静汤,提高了重傳的效率琅催。
快恢復:上面的擁塞控制會在網絡擁塞時將擁塞窗口降為1居凶,重新慢開始,這樣存在的一個問題就是網絡無法很快恢復到正常狀態(tài)藤抡∠辣蹋快恢復就是來優(yōu)化這個問題的,使用快恢復缠黍,則出現(xiàn)擁塞時弄兜,擁塞窗口只會降低到新的慢開始門閥值(即12),而不會降為1瓷式,然后直接開始進入擁塞避免加法增長替饿,如下圖所示:
快重傳和快恢復是對擁塞控制的進一步改進。
要更深入地理解本小節(jié)問題贸典,請詳讀:《TCP/IP詳解 - 第21章·TCP的超時與重傳》视卢、《通俗易懂-深入理解TCP協(xié)議(下):RTT、滑動窗口廊驼、擁塞處理》据过。
6、有關Socket
Socket是一組操作TCP/UDP的API妒挎,像HttpURLConnection和Okhttp這種涉及到比較底層的網絡請求發(fā)送的蝶俱,最終當然也都是通過Socket來進行網絡請求連接發(fā)送,而像Volley饥漫、Retrofit則是更上層的封裝榨呆,最后是依靠HttpURLConnection或者Okhttp來進行最終的連接建立和請求發(fā)送。
Socket的簡單使用的話應該都會庸队,兩個端各建立一個Socket积蜻,服務端的叫ServerSocket,然后建立連接即可彻消。
相關資料竿拆,請閱讀:
《網絡編程懶人入門(八):手把手教你寫基于TCP的Socket長連接》
《腦殘式網絡編程入門(二):我們在讀寫Socket時,究竟在讀寫什么宾尚?》
7丙笋、本文小結
當然,以上這些內容只是我自己知道的并且認為挺重要的計算機網絡基礎煌贴,還有非常多的網絡基礎知識需要去深入了解去探索御板。寫了很多,算是對自己網絡基礎的一個整理牛郑,可能也會有紕漏怠肋,權當拋磚引玉,還請各位大牛不吝賜教淹朋。
附錄:更多網絡基礎知識文章
《TCP/IP詳解 - 第11章·UDP:用戶數(shù)據(jù)報協(xié)議》
《TCP/IP詳解 - 第17章·TCP:傳輸控制協(xié)議》
《TCP/IP詳解 - 第18章·TCP連接的建立與終止》
《TCP/IP詳解 - 第21章·TCP的超時與重傳》
《技術往事:改變世界的TCP/IP協(xié)議(珍貴多圖笙各、手機慎點)》
《通俗易懂-深入理解TCP協(xié)議(上):理論基礎》
《通俗易懂-深入理解TCP協(xié)議(下):RTT钉答、滑動窗口、擁塞處理》
《理論經典:TCP協(xié)議的3次握手與4次揮手過程詳解》
《理論聯(lián)系實際:Wireshark抓包分析TCP 3次握手杈抢、4次揮手過程》
《計算機網絡通訊協(xié)議關系圖(中文珍藏版)》
《UDP中一個包的大小最大能多大数尿?》
《P2P技術詳解(一):NAT詳解——詳細原理、P2P簡介》
《P2P技術詳解(二):P2P中的NAT穿越(打洞)方案詳解》
《P2P技術詳解(三):P2P技術之STUN惶楼、TURN砌创、ICE詳解》
《通俗易懂:快速理解P2P技術中的NAT穿透原理》
《高性能網絡編程(一):單臺服務器并發(fā)TCP連接數(shù)到底可以有多少》
《高性能網絡編程(二):上一個10年,著名的C10K并發(fā)連接問題》
《高性能網絡編程(三):下一個10年鲫懒,是時候考慮C10M并發(fā)問題了》
《高性能網絡編程(四):從C10K到C10M高性能網絡應用的理論探索》
《高性能網絡編程(五):一文讀懂高性能網絡編程中的I/O模型》
《高性能網絡編程(六):一文讀懂高性能網絡編程中的線程模型》
《不為人知的網絡編程(一):淺析TCP協(xié)議中的疑難雜癥(上篇)》
《不為人知的網絡編程(二):淺析TCP協(xié)議中的疑難雜癥(下篇)》
《不為人知的網絡編程(三):關閉TCP連接時為什么會TIME_WAIT嫩实、CLOSE_WAIT》
《不為人知的網絡編程(四):深入研究分析TCP的異常關閉》
《不為人知的網絡編程(五):UDP的連接性和負載均衡》
《不為人知的網絡編程(六):深入地理解UDP協(xié)議并用好它》
《不為人知的網絡編程(七):如何讓不可靠的UDP變的可靠?》
《網絡編程懶人入門(一):快速理解網絡通信協(xié)議(上篇)》
《網絡編程懶人入門(二):快速理解網絡通信協(xié)議(下篇)》
《網絡編程懶人入門(三):快速理解TCP協(xié)議一篇就夠》
《網絡編程懶人入門(四):快速理解TCP和UDP的差異》
《網絡編程懶人入門(五):快速理解為什么說UDP有時比TCP更有優(yōu)勢》
《網絡編程懶人入門(六):史上最通俗的集線器窥岩、交換機甲献、路由器功能原理入門》
《網絡編程懶人入門(七):深入淺出,全面理解HTTP協(xié)議》
《網絡編程懶人入門(八):手把手教你寫基于TCP的Socket長連接》
《技術掃盲:新一代基于UDP的低延時網絡傳輸層協(xié)議——QUIC詳解》
《讓互聯(lián)網更快:新一代QUIC協(xié)議在騰訊的技術實踐分享》
《現(xiàn)代移動端網絡短連接的優(yōu)化手段總結:請求速度颂翼、弱網適應晃洒、安全保障》
《聊聊iOS中網絡編程長連接的那些事》
《移動端IM開發(fā)者必讀(一):通俗易懂,理解移動網絡的“弱”和“慢”》
《移動端IM開發(fā)者必讀(二):史上最全移動弱網絡優(yōu)化方法總結》
《IPv6技術詳解:基本概念朦乏、應用現(xiàn)狀球及、技術實踐(上篇)》
《IPv6技術詳解:基本概念、應用現(xiàn)狀呻疹、技術實踐(下篇)》
《從HTTP/0.9到HTTP/2:一文讀懂HTTP協(xié)議的歷史演變和設計思路》
《腦殘式網絡編程入門(一):跟著動畫來學TCP三次握手和四次揮手》
《腦殘式網絡編程入門(二):我們在讀寫Socket時吃引,究竟在讀寫什么?》
《腦殘式網絡編程入門(三):HTTP協(xié)議必知必會的一些知識》
《腦殘式網絡編程入門(四):快速理解HTTP/2的服務器推送(Server Push)》
《以網游服務端的網絡接入層設計為例刽锤,理解實時通信的技術挑戰(zhàn)》
《邁向高階:優(yōu)秀Android程序員必知必會的網絡基礎》