TCP必須使用端到端擁塞控制而不是使網絡輔助的擁塞控制,因為IP層不向端系統提供顯式的網絡擁塞反饋。TCP采用的方法是讓每一個發送方根據所感知到的網絡擁塞程度來限制其能向連接發送流量的速率。
幾個相關概念:
1. MSL
MSL 是Maximum Segment Lifetime英文的縮寫,中文可以譯為“報文最大生存時間”,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。
2. TTL
IP頭中有一個TTL域,TTL 是 time to live的縮寫,中文可以譯為“生存時間”,這個生存時間是由源主機設置初始值但不是存的具體時間,而是存儲了一個ip數據報可以經過的最大路由數,每經 過一個處理他的路由器此值就減1,當此值為0則數據報將被丟棄,同時發送ICMP報文通知源主機。RFC 793中規定MSL為2分鍾,實際應用中常用的是30秒,1分鍾和2分鍾等。
TTL與MSL是有關系的但不是簡單的相等的關系,MSL要大於等於TTL。
3. RTT
RTT是客戶到服務器往返所花時間(round-trip time,簡稱RTT),TCP含有動態估算RTT的算法。TCP還持續估算一個給定連接的RTT,這是因為RTT受網絡傳輸擁塞程序的變化而變化
4. MSS: Maximum Segment Size 最大報文段長度
TCP限制向其連接發送流量
TCP連接的每一端都是由一個接收緩存、一個發送緩存和幾個變量組成。運行在發送方的TCP擁塞控制機制跟蹤一個額外的變量,擁塞窗口(cwnd),它對一個TCP發送方能向網絡中發送流量的速率進行了限制:在一個發送方中未被確認的數據量不會超過cwnd和rwnd中的最小值,即 LastByteSent - LastByteAcked <= min{cwnd, rwnd}.
通過約束發送方中未被確認的數據量,間接限制了發送方的發送速率。考慮一個丟包和發送時延均可以忽略不計的連接。在每個往返時間 (RTT)的起始點,上面的限制條件允許發送方向該連接發送cwnd個字節的數據,在該RTT結束時發送方接收對數據的確認報文。因此,該發送方的發送速率大概為 cwnd/RTT 字節/秒。
TCP檢測網絡發生擁塞
當出現超時未反饋或者收到接收方的3個冗余ACK,則出現丟包事件。則發送方認為在發送方到接收方的路徑上出現了擁塞的指示。
冗余ACK是指接收方回給發送方和之前的ACK相同的一個ACK。這出現在,當接收方本應該接收X字節開頭的報文,卻收到X字節之后的某字節開頭的報文(即X字節開始的報文丟失)時,接收方返回給發送方和上次相同的ACK報文,即報文的確認號位置仍然填寫X。
這樣發送方就知道X字節開始的報文丟失,從而會重傳X字節開頭的報文。
TCP擁塞控制算法
TCP擁塞控制算法包括慢啟動、擁塞避免、快速恢復三個部分。
1. 慢啟動
TCP連接開始時,cwnd的值通常初始置為一個MSS的較小值,這就使得初始發送速率大約為 MSS/RTT;之后,每收到一個報文段的首次被確認cwnd就增加一個MSS。這樣,第一個RTT中,cwnd為1 MSS, 第二個RTT中,cwnd為2 MSS, 第三個RTT中,cwnd為4 MSS, 即每個RTT之后,cwnd就翻倍,cwnd呈指數增長。
當發生丟包時,設置一個變量 ssthresh(慢啟動閾值) = cwnd / 2, 然后cwnd重新設為1。
2. 擁塞避免
當出現丟包時,如果(可能會直接進入快速恢復)進入慢啟動階段,ssthresh設為 cwnd/2, cwnd值置為1,然后每個RTT cwnd翻倍,當cwnd值到達 ssthresh之后,進入擁塞避免階段。
此時,每個RTT,cwnd值只增加1個MSS,即每收到一個報文的ACK,cwnd = cwnd + MSS/cwnd.直到再次出現丟包后。當出現超時類型的丟包時,進入慢啟動階段(ssthresh = cwnd/2, cwnd=1);當出現三次冗余ACK類型的丟包時,進入快速恢復階段(ssthresh = cwnd/2, cwnd = ssthreash + 3MSS)
3. 快速恢復
當出現三次冗余ACK類型的丟包時,進入快速恢復階段。此時 ssthresh = cwnd/2, cwnd = ssthreash + 3MSS,之后每個RTT內,cwnd增加1個MSS,直到出現丟包。