【14】TCP/IP協議族詳解-TCP(3)

本博客參考自《TCP/IP詳解卷一:協議》

本文主要介紹TCP中的超時重傳

1.往返時間RTT的計算

TCP提供可靠的運輸層,其中重要的方法之一就是確認從另一端收到的數據。但數據和確認都有可能丟失。TCP通過在發送時設置一個定時器來解決這個問題。如果定時器溢出時還沒有收到確認,就重傳數據。

TCP超時和重傳中最重要的部分是對一個給定連接的往返時間(RTT)的測量。在網絡傳輸的過程中,這個值經常是變化的。RTT的測量必須是在同一報文的發送和確認之間。

較早的時候是通過低通濾波器來更新一個被平滑的RTT估計器來計算超時重傳時間RTO(retransmission timeout)。用M表示測量的RTT,R表示被平滑的RTT估計值。

R\leftarrow \alpha R+(1-\alpha ))M

RTO=\beta R

這裏的\alpha一般取值0.9,\beta一般取值2。這種方法在RTT的變化範圍很大的時候,無法跟上變化,從而引起不必要的重傳。所以提出了一種新的方法。除了被平滑的RTT估計器,還需要根據RTT的方差。這種計算方法在往返時間起伏很大的時候可以得到一個較好的響應。

Err=M-A

A\leftarrow A+gErr

D\leftarrow D+h(\left | Err \right |-D)

RTO=A+4D

這裏A是被平滑的RTT而D是被平滑的均值偏差。Err是剛得到的測量結果與之前的RTT估計器之差。增量g起平均作用,一般取值0.125。h是偏差的增益,一般取0.25。當RTT增大時,較大的偏差增益將使RTO快速上升。

1.1 Karn算法

在一個分組重傳時會產生這樣一個問題:假定一個分組被髮送。當超時發生時, RTO會進行退避(增長),分組以更長的RTO進行重傳,然後收到一個確認。這個確認是針對第一個或第二個分組,難以確認。這就導致重傳的二義性。

Karn算法規定,當一個超時和重傳發生時,在重傳數據的確認最後達到之前,不能更行RTT估計器。

1.2 RTT計算舉例

在這個例子中,客戶端一共向服務器發送了32678字節的數據,這裏只截取了一部分。

從上圖中可以看出,RTT的更新只在同一報文的確認到達時才啓動。TCP中內置了一個500ms的定時器,沒發送一次數據時,這個定時器都會啓動。在報文4時,該定時器已經在啓動的狀態,所以不會對報文段4進行計時,同理7,9報文段。

注意這個定時器同我們理解的定時器不同,它記錄的是時鐘的滴答,即只要時鐘經過一個滴答定時器就加1,記錄一個500ms。舉例來說,在系統時鐘某一滴答後的490ms,你啓動了定時器。10ms後系統時鐘經歷一次滴答,你的定時器就會定時500ms,雖然此時真實的時間只有10ms。

上圖顯示了實際的RTT同系統時鐘的滴答之間的關係,圖中虛線表示系統時鐘的滴答時刻。可以看出,RTT #1經歷的時鐘滴答爲3,RTT #2經歷的時鐘滴答爲1,RTT #3經歷的時鐘滴答爲2。

下面根據RTT對RTO的值進行估計計算

①初始化A和D分別爲0和3

RTO=A+2D=0+2\times 3=6s

因子2D只在初始化的時候出現,後面的計算都會以4D代替。

②同步報文超時重傳,RTO指數退避

RTO=A+4D=0+4\times 3=12s

③確認報文2到達

由於估計值A一開始的值爲0,所以估計器A需要被初始化。此時RTT爲3個時鐘滴答,所以M的值爲1.5

A=M+0.5=2

D=A/2 = 1

RTO=A+4D = 6s

③確認報文5到達,RTT爲1個時鐘滴答,M的值爲0.5

Err=M-A=0.5-2=-1.5

A=A+gErr=2-0.125\times 1.5=1.8125

D=D+h(\left | Err \right |-D)=1+0.25\times (1.5-1)=1.125

RTO=A+4D=1.8125+4\times 1.125=6.3125

④報文段10到達,RTT爲2個時鐘滴答,M的值爲1

Err=M-A=1-1.8125=-0.8125

A=A+gErr=1.8125-0.125\times 0.8125=1.37109375

D=D+h(\left | Err \right |-D)=1.125+0.25\times (0.8125-1.125)=1.046875

RTO=A+4D=1.37109375+4\times 1.046875=5.55859375

下圖是測量的RTT和RTO的曲線

上表是確認報文2到達開始計算的。

2.擁塞避免算法

網絡通信有時會達到中間路由器的極限,分組會丟失。擁塞避免是處理這種丟失分組的方法。該方法假設,分組丟失是由源主機和目的主機之間的某處網絡故障造成的。有兩種情況表示分組丟失:發生超時和接收到重複確認。

當擁塞發生時,爲了降低分組進入網絡的傳輸速率,需要調用慢啓動算法來實現。擁塞避免和慢啓動算法需要對每個連接維持兩個變量一個擁塞窗口cwnd和一個慢啓動門限ssthresh。這樣得到的算法的工作過程如下:

1) 對一個給定的連接,初始化cwnd爲1個報文段,ssthresh爲6 5 5 3 5個字節。
2) TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小。擁塞避免是發送方使用的流量控制,而通告窗口則是接收方進行的流量控制。前者是發送方感受到的網絡擁塞的估計,而後者則與接收方在該連接上的可用緩存大小有關。
3) 當擁塞發生時(超時或收到重複確認),ssthresh被設置爲當前窗口大小的一半(cwnd)和接收方通告窗口大小的最小值,但最少爲 2個報文段)。此外,如果是超時引起了擁塞,則cwnd被設置爲1個報文段(這就是慢啓動)。
4) 當新的數據被對方確認時,就增加cwnd,但增加的方法依賴於我們是否正在進行慢啓動或擁塞避免。如果cwnd小於或等於ssthresh,則正在進行慢啓動,否則正在進行擁塞避免。慢啓動一直持續到我們回到當擁塞發生時所處位置的半時候才停止(因爲記錄了在步驟 2中給我們製造麻煩的窗口大小的一半),然後轉爲執行擁塞避免。

擁塞避免算法要求每次收到一個確認時將cwnd增加爲1/cwnd。這樣就保證理想情況下每個往返時間增加一個窗口大小。這是一種線性增長。下圖展示了慢啓動和擁塞避免算法的工作流程。

cwnd=32時發送擁塞,接着ssthresh=32/2=16,cwnd=1,這時執行慢啓動算法。當cwnd=16時,慢啓動算法失效,每個RTT內只增加一個cwnd

3.快速重傳和快速恢復算法

TCP的連接中,當收到3個以上的重複ACK,就認爲是報文段的丟失。接下來就會重傳數據報文段,無需等待超時定時器溢出。這就是快速重傳算法。快速重傳算法首先執行擁塞避免算法,而不是慢啓動,這就是說cwnd不會變爲1。算法的具體流程如下:

1) 當收到第3個重複的ACK時,將ssthresh設置爲當前擁塞窗口cwnd的一半。重傳丟失的報文段。設置cwndssthresh加上3倍的報文段大小。
2) 每次收到另一個重複的ACK時,cwnd增加1個報文段大小併發送 1個分組(如果新的cwnd允許發送)。
3) 當下一個確認新數據的A C K到達時,設置cwndssthresh(在第1步中設置的值)。這個ACK應該是在進行重傳後的一個往返時間內對步驟 1中重傳的確認。另外,這個ACK也應該是對丟失的分組和收到的第 1個重複的ACK之間的所有中間報文段的確認。這一步採用的是擁塞避免,因爲當分組丟失時將當前的速率減半。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章