補充tcp協議與滑動窗口
咱們在向對端發送數據時,並非一股腦子任意發送,由於TCP創建鏈接後,就是創建了一根管道,這跟管道上,實際上有不少的工做設備,好比路由器和交換機等等,他們都會對接收到的TCP包進行緩存,以便實現排序,而後發送,可是這些設備並非只爲一個TCP鏈接中轉數據包,大量的網絡包也許會耗盡存儲空間,從而致使TCP鏈接的吞吐量急劇降低。爲了不這種狀況的發送,TCP的設計必須是一種無私的協議,它必須去探測這種網絡擁塞的問題,不然咱們想一想,一旦出現擁塞(判斷是否丟包或者是否發生重傳),若是TCP只能作重傳,那麼重傳數據包會使得網絡上的包更多,網絡的負擔更重,因而致使更大的延遲以及丟更多的包,因而會進入一個惡性循環,若是網絡上的全部TCP鏈接都是如此行事的話,那麼立刻就會造成「網絡風暴」,會拖垮整個網絡,這也是一個災難。那麼TCP就應該可以檢測出來這種情況,當擁塞出現時,要作自我犧牲,就像交通阻塞同樣,每一輛車都應該把路給讓出來,而不是再去搶路了。這說的就是擁塞控制。那是如何控制的呢?算法
首先,咱們得看TCP是如何充分利用網絡的,TCP實際上就是逐步探測這個通道的傳輸的最大能力,這個逐步探索就是咱們要講的慢啓動算法,這個慢啓動算法就是:新創建的鏈接不能一開始就大量發送數據包,而是應該根據網絡情況,逐步地增長每次發送數據包的量。segmentfault
具體的工做步驟就是:緩存
慢啓動算法:網絡
擁塞避免階段ssh
這樣放緩了擁塞窗口的增加速率,避免增加過快致使網絡擁塞,慢慢的增長調整到網絡的最佳值。在這個過程當中若是出現了擁塞,則進入擁塞狀態。
擁塞狀態 那是如何判斷出現擁塞狀態呢?只要出現丟包就認爲進入了擁塞狀態。進入擁塞狀態也分兩種狀況:
1) 等到RTO超時(重傳超時),重傳數據包。TCP認爲這種狀況太糟糕,反應也很強烈:tcp
快速重傳
2)連續收到3個duplicate ACK時,重傳數據包,無須等待RTO。此狀況即爲下面的快速重傳。網站
【問題】什麼狀況下會出現3個duplicate ACK?設計
TCP在收到一個亂序的報文段時,會當即發送一個重複的ACK,而且此ACK不可被延遲。排序
若是連續收到3個或3個以上重複的ACK,TCP會斷定此報文段丟失,須要從新傳遞,而無需等待RTO。這就叫作快速重傳。路由
TCP Tahoe的實現和RTO超時同樣。 TCP Reno的實現是:
上面咱們能夠看到RTO超時後,sshthresh會變成cwnd的一半,這意味着,若是cwnd<=sshthresh時出現的丟包,那麼TCP的sshthresh就會減了一半,而後等cwnd又很快地以指數級增漲爬到這個地方時,就會成慢慢的線性增漲。咱們能夠看到,TCP是怎麼經過這種強烈地震盪快速而當心得找到網站流量的平衡點的。
快速恢復算法
這個算法定義在RFC5681。快速重傳和快速恢復算法通常同時使用。快速恢復算法是認爲,你還有3個Duplicated Acks說明網絡也不那麼糟糕,因此沒有必要像RTO超時那麼強烈。 注意,正如前面所說,進入Fast Recovery以前,cwnd 和 sshthresh已被更新:
而後,真正的Fast Recovery算法以下:
若是咱們仔細思考一下上面的這個算法,你就會知道,上面這個算法也有問題,那就是——它依賴於3個重複的Acks。注意,3個重複的Acks並不表明只丟了一個數據包,頗有多是丟了好多包。但這個算法只會重傳一個,而剩下的那些包只能等到RTO超時,因而,進入了惡夢模式——超時一個窗口就減半一下,多個超時會超成TCP的傳輸速度呈級數降低,並且也不會觸發Fast Recovery算法了。
因而,1995年,TCP New Reno(參見 RFC 6582 )算法提出來:
咱們能夠看到,這個「Fast Recovery的變動」是一個很是激進的玩法,他同時延長了Fast Retransmit和Fast Recovery的過程。