面試突擊69:TCP 可靠嗎?為什麼?

相比於 UDP 來說,TCP 的主要特性是三個:有連接、可靠、面向數據流。所謂的「有連接」指的是 TCP 中的連接管理機制,也就是著名的三次握手和四次揮手,就像打電話一樣,想要正常的交流,必須先和對方建立起連接,這就是所謂的「有連接」,而面向數據流的機制咱們以後再講,我們今天要討論的主題是:TCP 是如何保證可靠性的?
TCP 之所以能保證可靠性,主要是通過以下 6 個手段:

  1. 校驗和
  2. 確認應答
  3. 超時重傳
  4. 流量控制
  5. 擁塞控制
  6. 丟棄重複數據

接下來,我們詳細來看這幾種手段的具體實現。

1.校驗和

TCP 協議的數據格式如下圖所示:

(圖片來源:許許如生xxrs)
從上圖可以看出「校驗和」是保存在 TCP 首部中的一個數據,TCP 的發送端和接收端會採用相同的演算法,根據發送的數據計算出一個 16 位的校驗和,並且校驗和會連同數據一起發送給接收端。
接收端在得到數據之後,會根據接收的數據生成一個新的校驗和,然後用新的校驗和與傳遞過來的校驗和做對比,如果校驗和相同,那麼說明數據在傳遞過程中沒有發生任何改變,是一個有效的數據,反之則為無效數據,捨棄即可。

校驗和基本演算法

TCP/UDP/IP 等協議的校驗和演算法都是相同的,採用的都是將數據流視為 16 位整數流進行重複疊加計算。為了計算檢驗和,首先把檢驗和欄位置為 0,然後,對有效數據範圍內中每個 16 位進行二進位反碼求和,結果存在檢驗和欄位中,如果數據長度為奇數則補一位元組 0。當收到數據後,同樣對有效數據範圍中每個 16 位數進行二進位反碼的求和。由於接收方在計算過程中包含了發送方存在首部中的檢驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那麼接收方計算的結果應該為全 0 或全 1(具體看實現了,本質一樣) 。如果結果不是全 0 或全 1,那麼表示數據錯誤。

2.確認應答

確認應答機制是保證消息傳遞可靠性的關鍵手段,也是幾乎所有消息中間件(MQ)中,最常用的技術之一,比如主流的消息中間件 RabbitMQ、Kafka、RocketMQ 中都有確認應答機制,也就是我們常說的 ACK(ACKnowledge Character,確認字元)。
確認應答機制是 TCP 中,保證消息可靠性的核心機制。怎麼才能確認你發的消息對方一定收到了呢?最有效的手段無疑是對方告訴你,它已經收到了,這就是確認應答。
確認應答的流程如下圖所示:
image.png

3.超時重傳

消息在確認應答的過程中可能會出現兩個問題:第一,消息在發送的時候丟失了,第二,消息在確認應答時丟失了,如下圖所示:
image.png
顯然,即使有了確認應答機制也保證不了消息不丟失,那怎麼辦呢?
消息丟了沒關係,發送端在確認了消息丟失之後,再補償一個同樣的消息給接收端不就解決了?這就是超時重傳機制。

巧妙的超時重傳機制

TCP 的超時重傳機制在設計上也非常巧妙,它為了保證消息在任何環境中,都能高效的通訊,所以 TCP 採用的是「動態時間」的超時重傳機制。
比如第一次如果消息丟了,那麼發送端會在 500ms 之後再發送一個消息,如果發送的第二個消息也丟了,那麼發送端會在 1000ms 之後再發送一個消息,如果第三個消息也丟了,那麼它會在 2000ms 之後再發送一個消息,如果累計了一定的次數,消息還沒有成功的發送,那麼 TCP 會認為對方主機存在異常,會強制關閉連接,這就是 TCP 超時重傳的主要執行流程。

4.流量控制

接收端處理數據的速度是有限的,如果發送端發的太快,那麼就會導致接收端的緩衝區被打滿,這個時候如果發送端繼續發送,就會造成丟包,繼而引起丟包重傳等等一系列連鎖反應。
因此 TCP 會根據接收端的處理情況,動態調整發送數據的大小,這個機制就叫流量控制(Flow Control)。

5.擁塞控制

擁塞控制指的是 TCP 會根據當前網路的情況,動態的控制發送數據的多少,以適合的速度來傳遞數據。
想像一下,如果 TCP 在不清楚網路情況的環境下,貿然的發送大量的數據給接收端,這樣就會導致更多的丟包及超時重傳,從而引起一系列的連鎖反應,導致數據傳遞變慢。
而 TCP 採取的是「慢啟動」機制,先發少量的數據,探探路,摸清當前的網路擁堵狀態,再決定按照多大的速度傳輸數據,這就是擁塞控制機制。
如果傳遞的數據多了,出現了大量的丟包,那麼 TCP 會將發送的數據量調小,然後再嘗試慢慢的增加發送的數據量,通過這種動態發送數據包的形式,來實現適合當前網速的數據傳遞,這就是 TCP 擁塞控制的具體實現。

6.丟棄重複數據

通過前面的知識我們知道,在確認應答時,由於確認應答消息的丟失,那麼接收方可能會收到發送方的重複數據,如下圖所示:
image.png
而此時對於業務方來說,只需要一個數據就可以了,所以 TCP 還有一個機制,丟棄重複數據的機制,這樣就能保證業務方接收到的數據是正確的了。
TCP 會給每一個發送的包上加上一個編號,如果接收到了編號相同的數據包,那麼就說明接收端得到了重複的包,丟棄即可。

總結

TCP 保證可靠性的主要手段有 6 個:校驗和、確認應答、超時重傳、流量控制、擁塞控制、丟棄重複數據。其中流量控制和擁塞控制很容易搞混,我們要清楚的知道,流量控制是針對接收端接收能力的控制機制,而擁塞控制是針對當前網路的控制機制,所以千萬不要搞混了。

參考 & 鳴謝

blog.csdn.net/namelcx/article/details/6866720

是非審之於己,毀譽聽之於人,得失安之於數。

公眾號:Java面試真題解析

面試合集://gitee.com/mydb/interview

Tags: