繞不開的TCP之超時重傳

前文介紹了TCP建立連接和斷開連接的方式。那在連接建立之後,TCP如何保證數據的可靠傳輸的呢?畢竟現實的網絡環境是這樣的複雜,出錯、超時和丟包的種種問題時有發生,背後的祕密在哪裏呢?跟隨我們的文章,一起探究一下吧。

TCP重傳機制

TCP協議是一種面向連接的可靠的傳輸層協議,它保證數據可靠傳輸的基本原理是在發送一個數據之後,就開啓一個定時器,若是在這個時間內沒有收到剛纔發送數據的ACK確認報文(是通過確認序號的方式進行確認,即剛纔發送數據的序列號+1),則對該報文進行重傳。如果一直失敗,滿一定次數後就會放棄併發送一個復位信號。

顯而易見,這個定時器的時間(RTO)相當關鍵,關係着網絡資源是否被有效利用。

如果RTO設置過小,部分報文可能遇到網絡擁堵或者延遲比較大的情形,這樣就會頻繁重傳,浪費帶寬。如果RTO設置過大的話,發送端需要等待過長時間才能發現數據丟失,影響網絡的傳輸效率,造成的表象就是後端系統響應時間過長甚至超時,顯然會給用戶造成惡劣的影響,這是我們需要堅決規避的。

那設置RTO是否有依據呢?

一般RTO是根據網絡中的RTT(傳輸往返時間)來自適應調整的。具體算法這邊就不贅敘了。

接下來讓我們通過兩幅圖來了解一下重傳機制吧。
在這裏插入圖片描述
主機A發送數據給B之後, 可能因爲網絡擁堵等原因, 數據無法到達主機B。
如果主機A在一個特定時間間隔內沒有收到B發來的確認應答, 就會進行重發。

但是主機A沒收到確認應答也可能是ACK丟失了,如下圖所示。

在這裏插入圖片描述
這種情況下, 主機B會收到很多重複數據。

那麼TCP協議需要識別出哪些包是重複的, 並且把重複的丟棄。那TCP是如何去重的呢?

答案就是序列號(TCP將每個字節的數據都進行的編號),如下圖所示:

在這裏插入圖片描述
每次主機B的確認應答都帶有對應的確認序列號, 用來告知主機A, 我已經收到了哪些數據(收到的數據爲確認序列號-1以下的字節數據),下一次你要從哪裏開始發送,而已經接收的數據序列號會緩存在本地等待上層應用程序消費,如果已經重複了,則會丟棄。

比如, 主機A向主機B發送了1005字節的數據, 服務器返回給客戶端的確認序號是1003, 那麼說明服務器只收到了1-1002的數據. 1003的數據肯定沒有收到,至於1004, 1005則不確定,即使收到了,也會暫時緩存, 等主機A重發1003收到後,直接向主機A確認應答,此時確認序列號應該爲1006。

重傳定時器

上面的定時器被稱作重傳定時器(Retransmission Timer),其在TCP發送報文段時,就會被創建(與該特定報文相關)。可能發生以下兩種情況:
1.若在計時器截止時間到之前收到了對此特定報文段的確認,則撤銷此計時器。

2.若在收到了對此特定報文段的確認之前計時器截止時間到,則重傳此報文段,並將計時器復位。

是否還有其他定時器呢?如果有,它們又分別應用在什麼場景呢?

(1)堅持計時器

先來考慮以下情景:發送端向接收端發送數據包直到接收窗口填滿了,然後接收窗口告訴發送方接收窗口填滿了,請停止發送數據。此時的狀態稱爲“零窗口”狀態,發送端和接收端窗口大小均爲0。直到接收TCP發送確認並宣佈一個非零的窗口大小,但這個確認會丟失。

衆所周知,TCP對確認是不需要發送確認的。若確認丟失了,接收TCP並不知道,而是會認爲它已經完成了任務,並等待着發送TCP接着會發送更多的報文段。但發送TCP由於沒有收到確認,就一直等待對方發送確認來通知窗口大小,由此導致雙方的TCP都在永遠的等待着對方。要打開這種死鎖,TCP需要爲每一個鏈接使用一個堅持計時器。

當發送TCP收到窗口大小爲0的確認時,就啓動堅持計時器。當堅持計時器期限到時,發送TCP就發送一個特殊的報文段,叫做探測報文。這個報文段只有一個字節的數據。它有一個序號,但它的序號永遠不需要確認;甚至在計算機對其他部分的數據的確認時該序號也被忽略。探測報文段提醒接收TCP:確認已丟失,必須重傳。堅持計時器的值設置爲重傳時間的數值。但是,若沒有收到從接收端來的響應,則需發送另一個探測報文段,並將堅持計時器的值加倍和復位。發送端繼續發送探測報文段,將堅持計時器設定的值加倍和復位,直到這個值增大到門限值(通常是60秒)爲止。在這以後,發送端每隔60秒就發送一個探測報文,直到窗口重新打開。

(2)保活計時器

保活計時器使用在某些實現中,用來防止在兩個TCP之間的連接出現長時間的空閒。假定客戶端建立了到服務器的連接,並傳送了一些數據,然後就保持靜默了。也許是這個客戶出故障了。在這種情況下,這個連接將永遠的處理打開狀態。
要解決這種問題,在大多數的實現中都是使服務器設置保活計時器。每當服務器收到客戶的信息,就將計時器復位。通常設置爲兩小時。若服務器過了兩小時還沒有收到客戶的信息,他就發送探測報文段。若發送了10個探測報文段(每一個75秒)還沒有響應,就假定客戶除了故障,因而就終止了該連接。這種連接的斷開當然不會使用四次握手,而是直接硬性的中斷和客戶端的TCP連接。

(3)時間等待計時器

時間等待計時器是在四次握手的時候使用的,上文已經提到過,這邊就不重複了。

以上是關於TCP超時重傳的探索,希望可以給大家帶來收穫。

其他文章可以關注微信公衆號測試架構師養成記,還有價值999的資料可以領哦~
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章