天天看點

《Wireshark網絡分析的藝術》—被誤解的TCP

本節書摘來自異步社群《wireshark網絡分析的藝術》一書中的被誤解的tcp,作者林沛滿,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

被誤解的tcp

wireshark網絡分析的藝術

人一旦形成某種思維定勢,就很難再改變了。知道我收到最多的讀者來信是問什麼嗎?“林工,有些tcp包發出去之後沒有看到對應的ack,算不算丢包啊?”這個問題讓我很是好奇,明明rfc上沒有這樣的規定,為什麼總有讀者覺得每一個資料包都應該有對應的ack呢?後來才注意到,很多提問者是做網站開發出身的,已經習慣了每個http請求發出去,就一定會收到一個http響應(見圖1),是以就把這個模式套到了tcp上。其實不止http,絕大多數應用層協定都采用這種一問一答的工作方式。

《Wireshark網絡分析的藝術》—被誤解的TCP

tcp當然也可以采用這種方式,但并非必要。就像我們不用每天都跟公司算一次工錢,而是攢到月底結算一樣,資料接收方也可以累積一些包才對發送方ack一次。至于ack的頻率,不同的作業系統有不同的偏好,比如我實驗室中的linux用戶端喜歡每收到兩個包ack一次,見圖2。

《Wireshark網絡分析的藝術》—被誤解的TCP

而windows用戶端則懶得多,隔好多個包才ack一次,見圖3的97号包。

《Wireshark網絡分析的藝術》—被誤解的TCP

這兩種方式都是正常的,但linux對流量更“大手大腳”一點,因為純ack也算流量的。其實在網絡帶寬越來越大的今天,人們已經不在乎這種小流量了。不過手機作業系統還是要慎重考慮的,畢竟蜂窩資料是按流量計費的,能省一點是一點。我的安卓手機就是每收到一個包都會ack的,想到這裡我的心都在滴血。圖4是我在微網誌上打開一張美女圖時産生的流量,你看這些密密麻麻的純ack,每個都白費我40位元組的流量。

《Wireshark網絡分析的藝術》—被誤解的TCP

也許以後會有手機廠商優化它,然後以此作為賣點。如果是從我這本書裡學到的,請為它命名“林朗台算法”。

既然接收方不一定收到每個包都要ack,那發送方怎麼知道哪些包雖然沒有相應的ack,但其實已經送達了呢?記住,ack是有累積效應的,它隐含了“在此之前的其他包也已收到”的意思,比如圖3中第97号包的ack=65701不僅表示收到了96号包(其seq+len=64273+1428=65701),而且暗示之前的其他包也都收到了。是以86~95号包雖然沒有被顯式ack,但發送方知道它們也已經被送達了。

另一個對tcp的廣泛誤解則和udp相關。有不少技術人員認為tcp的效率低,因為其傳輸過程中需要往返時間來确認(ack)。而udp無需确認,是以能不停地發包,效率就高了。事實真的如此嗎?這其實是對tcp傳輸機制的嚴重誤解。我們可以假設一個場景來類比tcp的工作方式:有大批貨物要從a地運往b地。如果隻用一輛貨車來運的話,馬路上就隻有一輛車在來回跑(回程相當于tcp的ack包),效率确實很低,對tcp的誤解可能也出自這個原因。但如果在不塞車的前提下盡量增加貨車數量,使整條馬路上充滿車,總傳輸效率就提高了。tcp發送視窗的意義相當于貨車的數量,隻要視窗足夠大,tcp也可以不受往返時間的限制而源源不斷地傳資料。這就是為什麼無論在區域網路還是廣域網,tcp還是最受歡迎的傳輸層協定。

當然tcp确實也有因為往返時間而降低效率的時候,比如在傳輸小塊資料的場景。本來能在1個往返時間完成的小事,卻要額外耗費3次握手和4次揮手的開銷,dns查詢就符合這種場景。目前http基本建立在tcp連接配接上,是以也會因為tcp的三次握手而增加延遲。你可能聽說過google釋出的quic(quick udp internet connection)協定,它就是為了消除tcp的延遲而設計的代替品。在某些領域可以視為tcp的競争對手,目前在google的網站上已經可以試用了。

本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。