TCP自己須要提供可靠的服務,方式之一就是確認接收方真的收到了數據,若是過了一段時間,即超時了,尚未收到確認的報文,認爲報文可能被丟失,就從新傳送報文,確保數據都能被收到html
超時發生重傳不必定重傳一樣的報文段,能夠從新分組發送一個較大的報文段,只要它不超過接收方聲明的MSSlinux
網絡流量和路由器在包的傳輸過程當中可能改變,所以RTT(Round Trip Time)也會變化,若是超時時間保持不變,假如RTT變的大了,可能出現ACK還在再發送的路上,卻直接重發了包,形成沒必要要的浪費算法
TCP經典算法RTT是:R <- αR + (1-α)M
,重傳時間爲 RTO=Rβ
緩存
其中M表示測量時間意思是發送一個某序列號的字節和接收到包含該序列號的確認之間的往返時間網絡
α是一個推薦值爲0.9的平滑因子: 對公式稍微作變形爲
R <- (1-g)R + gM
並從新組合R<-R+g(M-R)
,假設R是對下一個測量結果的預估,那麼 M-R 表示預估的結果和真實結果的誤差,整個公式所代表的就是預估的結果加上部分的預估誤差即爲新的預估結果。誤差可能包括兩部分,1是噪音,具備必定的隨機性,用Er表示,2是預估的錯誤,選用的R初始值有問題,用Ee表示,則R<-R+g*Er+g*Ee
,對於Ee來說,它的目標是把預估的結果往正確的方向去靠攏,而Er因爲存在必定的隨機性,通過多個樣本以後,可能最終影響的結果都互相抵消,那麼對於預估來說,但願Ee的因子要大些,Er的因子要小些,使得R的最終取值可以朝着正確的平均值去收斂,而對於Er來說不管g取何值都會使得結果往好的方向走,於是取g爲0.1-0.2能作一個好的值,也就是說α取值爲0.9,0.8便可tcp
R是估算的RTT的平均值ide
RTO表示重傳超時時間(Retransmission Timeout)意思是若是超過這個時間尚未收到ack就從新發送code
β 是RTT的變異係數,當傳輸時間能夠忽略不計的時候,最大時延和平均時延的變化最大,能夠看作全部的時延都是由於處理所形成的,這個時候最大值是平均值的兩倍,推薦β取值爲2。【假設往返時間最大值是R,若是傳輸時延忽略不計,那麼這兩次變化的平均傳輸時延就是0.5R,也就說最大值是平均值的兩倍】
β取值,詳見 https://tools.ietf.org/html/rfc813 第五章 和 jacobson算法 http://www.cs.binghamton.edu/~nael/cs428-528/deeper/jacobson-congestion.pdf
cdn
這種衡量方式沒有考慮到,RTT變化範圍很大的時候,經典的RTO的變化跟不上,從而引發沒必要要的重傳,此時網絡已經處於飽和狀態,再重傳更會增長網絡負載htm
jacobson算法中提到 β取值爲2,此時的負載最多爲30%,遠不能處理真實的狀況
另外一個沒有沒有解決的問題是,假定一個分組被髮送,當超時發生時,分組以更長的RTO進行重傳,而後收到一個確認,那麼收到的這個ACK是針對第一個分組仍是第二個分組呢?這種場景的解決方式是Karn算法,主要思想是超時和重傳發生時,在重傳數據的確認最後到達以前,不能更新RTT估算值
使用jacobson算法,RTO依賴於被平滑的RTT和被平滑的均值誤差,而不是均值的常數倍
實現代碼https://elixir.bootlin.com/linux/v2.6.32/ident/tcp_rtt_estimator
使用擁塞避免算法,它假定分組丟失就是由於網絡發生了擁塞。發送方使用兩個變量來作擁塞控制,一個是擁塞窗口cwnd,一個是慢啓動閾值ssthresh,當cwnd小於等於ssthresh時使用慢啓動,不然使用擁塞避免算法 。原則以下:
cwnd值加1會形成窗口按照指數方式增加,好比剛開始是1,那麼當它收到ack以後,下次發送兩個包,而後會收到兩個ack,cwnd立馬增加爲4,依此類推
cwnd值增長1/cwnd是一種加性增加,每接收到cwnd個包才加1
收到一個重複ack以後,其實沒法確認是報文丟失仍是報文段從新排序引發的,所以會等待少許重複ack到來,通常會等待3個或者以上。若是連續收到3個或以上的重複ack,則斷定可能報文丟失了,選擇立馬重傳,而不須要等待超時定時器溢出,這種方式稱爲快速重傳算法。接下來執行快速恢復算法,二者合併整個過程以下:
這個新的ACK應該是確認第一步中丟失的報文那一刻起發送的報文到第一步中重發的報文期間全部報文,包括第一步中重發的報文。
收到重複ack以後不執行慢啓動(即設置cwnd爲1),是由於收到重複的ack僅僅表示網絡中有數據丟失了。對於接收方而言,只有收到另外一個報文段纔會產生重複的ack,而該報文已經已經離開網絡並進入接收方的緩存,說明,收發端之間數據仍然在流動,不須要執行慢啓動來忽然減小數據流。 詳見 tools.ietf.org/html/rfc200… 第4章
整個過程圖例以下
在較新的TCP實現中,有一個路由表來維持指標,包括:被平滑的RTT、被平滑的均值誤差以及慢啓動門限。一個TCP鏈接關閉時,若是已經發送了16個窗口的數據(這就足夠多了),且目的節點的路由表不是默認的表向,就會存儲起來。創建鏈接是(部分主動仍是被動),只要路由表中有對應的值,就用它初始化
TCP常見的ICMP差錯包括源站抑制、主機不可達和網絡不可達
源站抑制指路由或者主機接收數據的速度比處理的速度快
把書讀薄(TCP/IP詳解 卷一 第二十一章)