文章目錄
- 一、TCP可靠傳輸實現
- 二、TCP超時重傳時間選擇
一、TCP可靠傳輸實現
??TCP可靠傳輸的實現,主要基于發送方和接收方的滑動窗口,以及確認機制:
- 發送方在未收到確認(ACK)前,可以將序號落在發送窗口內的數據段連續發送,但這些數據段必須保留在緩存中,不能釋放,以便在超時或接收到重復 ACK 時進行重傳。發送方的 滑動窗口表示 “允許發送但未確認” 的數據范圍;TCP 不會等待一個 ACK 才發送下一個段,而是可以 “流水線” 式發送多個段;
- 接收方在接收到發送方發送的報文后,要及時發送確認報文,如果接收到的報文段是不連續的,則會對連續報文段的最大序號及之前的數據進行確認。可以對發送方的滑動窗口大小進行調整(流量控制)。
??對于發送方和接收方的滑動窗口,都有前沿
和后沿
的概念:
- 發送方:
- 后沿:已發送并且接收到確認報文的數據,可以刪除。
- 前沿:在滑動窗口的最大范圍之外,不允許發送。
- 接收方:
- 后沿:已發送確認報文給發送方,并且這部分內容交付了應用進程,可以刪除。
- 前沿:在滑動窗口的最大范圍之外,不允許接收。
??為了維護發送窗口的狀態,可以使用P1,P2,P3三個指針:
- P1:指向的是發送窗口內已發送,但是還未收到確認的部分的第一個數據的序號。
- P2:指向的是發送窗口內還未發送的部分的第一個數據的序號。
- P3:指向的是發送窗口外的部分的第一個數據的序號。
??假設下圖的場景:
- 發送方已經成功發送了
4、5、6
三個報文段; - 接收方只成功收到了
5、6
,但沒有收到 4; - TCP 默認使用 累計確認(ACK) 策略 —— 只能確認連續收到的數據段。
??此時接收方收到的ACK應該為4,同時對5,6進行緩存。這種情況并不會引起發送方的快重傳,因為是第一次重復確認
??此時接收方收到了4的報文段,則反饋給發送方7的ack,表示已經接受到了4~6的報文段,現在要接受7的報文段,同時窗口向前滑動:
??假設此時發送方向接收方發送了7~10號報文段,但是接收方一直都沒有ack,因為窗口內的序號已經用完了,發送方在接收到接收方的確認之前,不能發送新的數據,而如果一直接收不到接收方的確認,就會觸發超時重傳(慢開始 + 擁塞避免算法)
二、TCP超時重傳時間選擇
??RTT = 請求的往返時間 = 請求開始時間 - 接收到請求確認的時間。RTO則是超時重傳的時間。RTO不能小于RTT,也不能遠大于RTT的值,應設置為略大于RTT的值。
??然而上述只是理想情況下的設置,實際網絡通信中,每次消息往返的時間都是不固定的,需要動態進行調整。
??RTT的計算也是非常復雜的,當發送方發生超時重傳的時候,無法知道接收方發出的確認報文段是針對原報文段的確認,還是重傳報文段的確認。(應是對于重傳報文段的確認)如果發送方將該報文段當做是對于原有報文段的確認,那么算出的RTT往返時間就會大于應有的值。
??同理,接收方在發送確認報文段發生了超時,導致發送方觸發了超時重傳。發送方無法知道接收方的確認報文段,是針對發送方第一次發送的報文的確認,還是超時重傳報文的確認(應該是對于發送方第一次報文的確認。)那么算出的RTT往返時間就會小于應有的值。
??針對上述的問題,提出了一種karn算法。Karn 算法是用于 計算 TCP 中的往返時間(RTT)和重傳超時時間(RTO) 的一個改進方法,專門用來避免因重傳而導致的 RTT 估算不準確問題。其核心思想在于不要用重傳報文段的 ACK 來更新 RTT 估算值。
- 當發生重傳時,不更新 RTT 估計值。
- 只用未發生重傳的報文段的 ACK 來估計 RTT。
- 啟用
指數退避
策略,即每次重傳失敗后,將 RTO 值加倍。