【前言】這個系列主要會介紹一些計算機網絡體系中「看上去稍有些複雜」但「一旦理解了又會很容易」的內容,我會嘗試經過示意圖/動圖的方式對概念進行儘可能直觀的詮釋,若是可以對你們學習計算機網絡有所啓發的話就最好了。緩存
TCP(Transmission Control Protocol)是整個TCP/IP協議族中爲數很少的能扛起「可靠傳輸」大旗的「扛把子」了(上有應用層協議嗷嗷待哺,下有IP協議寄予厚望(注:IP協議是不提供可靠傳輸服務的))可以肩負如此重任說明它的協議組成必定不簡單,不過,做爲一個「協議」,它必定也不會很難理解的。服務器
這部分的內容我打算分爲兩個部分講解,本篇文章主要會講解TCP鏈接的創建和釋放(三次握手+四次握手),以及發送端的滑動窗口通常原理;至於一樣很重要的「擁塞控制」等內容,我會放到下一篇文章中。網絡
提及TCP,咱們應該瞭解它最突出的特色是「基於鏈接的傳輸」和「以字節爲單位(面向字節流)」,這兩點特色與同是運輸層的UDP協議造成了鮮明對比。(UDP不創建鏈接,以報文爲單位,二者的區別有機會會仔細說說)而實現這兩點也是TCP可以提供可靠傳輸的關鍵。tcp
下面簡單解釋一下報文中一些重要的部分:學習
再瞭解了TCP報文結構以後,咱們須要知道,這裏的「報文」與咱們常見的「報文」有些不一樣。測試
TCP 不關心應用進程一次把多長的報文發送到 TCP 緩存。這和UDP的「給多少裝多少」正相反。
TCP 對連續的字節流進行分段,造成 TCP 報文段。
計算機網絡
那麼分段的依據是什麼呢?
TCP在創建鏈接的基礎上,發送方能夠根據對方給出的窗口值(接下來要提到的:使用滑動窗口實現流量控制)和當前網絡擁塞(下一篇文章將要提到的:擁塞控制機制)的程度來決定一個報文段應包含多少個字節(UDP 發送的報文長度是應用進程給出的)。blog
TCP 創建鏈接的過程叫作「握手」(handshake),能夠說是一個頗經典的不那麼貼切但爲你們所廣泛接受的擬人化稱呼。接口
在鏈接的創建階段,須要在客戶和服務器之間交換三個 TCP 報文段。稱之爲三報文握手(there-way handshake)。
進程
三報文握手的過程就如上動圖所示,是否是其實很簡單。
就像是兩個隔着很遠的人在測試一個電話線路:
「能聽見我說話嗎?」
「聽見了!能聽見我說話嗎?」
「聽見了!」
與創建鏈接思路類似的,還有「四報文握手」(four-way handshake)的鏈接釋放:
與創建鏈接不一樣的是,若是某一方想要釋放鏈接,另外一方「不必定」就想跟着釋放鏈接,由於它可能還有東西沒傳完呢。
就像是倆人打電話嘮了好久,其中有我的想要睡了:
「喂,我困了,咱明天再聊吧」
「哦哦,那我最後說幾句」
... ...
「好,我說完了,晚安咯」
「晚安」
滑動窗口,實際上就是發送方能連續發出的數據(字節流)的閾值。
如今假設,A收到了B發來的確認號爲32(代表B指望收到的下一個報文段的開頭序號爲32),窗口爲20字節的確認報文段,那麼A即可以根據這兩個數據構建出以下發送窗口:
A發送11個字節的數據後,發送窗口位置不變,可用窗口變小:
此時,B收到了前三個字節,向A發送確認號爲35的確認報文字段(同時接收窗口向前移動三個字節);
A的發送窗口在收到B的確認報文後也向前移動三個字節。
這裏,就須要引入「中止等待」和「累計確認」的概念了:
「中止等待」,顧名思義,就是每發送完一個分組就中止發送,等待對方的確認。在收到確認後再發送下一個分組。
而在TCP傳輸過程當中,爲了提升效率、節約資源,採用了「累計確認」的方式:即沒必要對收到的分組逐個發送確認,而是對按序到達的最後一個分組發送確認,表示到這個分組爲止的全部分組都已正確收到了。
接着,A繼續向B發送報文,可是B一直沒有發回確認報文。
A在發送至可用窗口爲零時便中止發送。
【後記】 運輸層真的是承上啓下的扛把子,這其中細節還有不少,今天挑了這兩個是由於對於這部分的內容,「直觀上的理解」比「文本上的記憶」更爲重要。 TCP的擁塞避免也是個很重要的內容,會出如今下一篇文章中。 最後,大家的反饋就是我最大的動力啦(逃