前言:
好久沒更新了,一直堆在筆記本里面,堆了有兩三篇博客了,一直懶得更新,今晚逼着自己更新=。= 新的寫法:摒棄了之前照抄書本的冗餘文字,大多數以自己的話來口述過程。雖然可能會不準確,但看起來更像是自己的東西哈哈。
何爲擁塞
客戶端發送數據太多,發送太快導致網絡中間層無法處理。表現:分組丟包、分組延遲大
擁塞控制的方法
- 端到端擁塞控制
端對端:ip層(網絡層)不反饋擁塞信息,只能通過端對端來控制,tcp通過超時事件或者三次冗餘的ack報文來判斷擁塞 - 網絡輔助擁塞控制
網絡輔助:網絡層的路由器向發送方提供顯式的反饋信息。
TCP擁塞控制
tcp主要採用的是端對端擁塞控制,原因是ip層不反饋擁塞信息。
書中的內容主要分爲一下三個問題。
如何控制?
通過控制擁塞窗口(cwnd)大小,即一次發送多少個數據報。
如何感知?
服務端接收3個冗餘的ack報文、超時事件
何種算法改變?
tcp擁塞控制算法:慢啓動、擁塞避免、快速恢復。
tcp擁塞控制算法
慢啓動
[MSS->報文段裏應用數據的最大值,未包含tcp報文段和ip數據報的首部,經典值爲1460]
[MTU->鏈路層中能夠承受的最大數據量叫做最大傳輸單元 經典值爲1500]
-
初始化狀態:cwnd的值爲一個MSS大小 ,即初始化狀態只能發送一個tcp報文
-
未到檢測到擁塞:沒收到一個ack確認報文,cwnd就加上一個MSS的值,所以cwnd以倍數形式增加 1-2-4-8-。。。。
-
檢測到擁塞: 存在兩種情況(1)超時指示的丟包 (2)三個冗餘ack報文
兩種情況的處理方式不同:
(1)超時指示的丟包:ssthresh(慢啓動閾值)設置爲cwnd的一半,然後把cwnd設置爲一個MSS的大小,重新開始慢啓動,此時的慢啓動當cwnd>=ssthresh的時候進入擁塞避免
(2)三個冗餘ack報文:ssthresh(慢啓動閾值)設置爲cwnd的一半,cwnd設置爲ssthresh(慢啓動閾值)的大小再加上3個MSS(用於重傳3個冗餘的ack報文對應的數據報----快速重傳),然後進入快速恢復
擁塞避免
[RTT->一個報文到達客戶端然後返回ACK報文,服務端接收到ACK報文所需的時間,簡稱往回時延]
進入擁塞避免狀態的tcp連接,說明此時的cwnd的值是上一次擁塞時的一半,所以此時cwnd的增長會比較的保守。
每收到一個ACK報文就會增加(MSS/cwnd)*MSS個字節。即加入MSS爲1460,cwnd此時是14600,那麼在一個RTT內發送了10個報文段,每個到達ACK增加十分之一個MSS,則在收到10個ACK報文才增長了1個MSS。
然後一直增加++++++直到檢測到擁塞:1)超時指示的丟包 (2)三個冗餘ack報文
似曾相識:
(1)超時指示的丟包:ssthresh(慢啓動閾值)設置爲cwnd的一半,然後把cwnd設置爲一個MSS的大小,重新開始慢啓動,此時的慢啓動當cwnd>=ssthresh的時候進入擁塞避免
(2)三個冗餘ack報文:ssthresh(慢啓動閾值)設置爲cwnd的一半,cwnd設置爲ssthresh(慢啓動閾值)的大小再加上3個MSS(用於重傳3個冗餘的ack報文對應的數據報----快速重傳),然後進入快速恢復
快速恢復
在快速恢復中對於引起tcp進入快速恢復的缺失報文,對每一個冗餘的ack報文,cwnd增加一個MSS,即3個。即一開始的狀態就是cwnd/2+3MSS
- 設置cwnd = ssthresh+ACK個數*MSS(一般情況下會是3個dup ACK)
- 重傳丟失的數據包(對於重傳丟失的那個數據包)
- 如果只收到Dup ACK,那麼cwnd = cwnd + 1個MSS
- 如果收到新的ACK, 設置cwnd = ssthresh, 是因爲該ACK確認了新的數據,說明從重複ACK時的數據都已收到,該恢復過程已經結束,可以回到恢復之前的狀態了,也即再次進入擁塞避免狀態。