天天看點

TCP之逾時和重傳

RTT:往返時間;  RTO:Retransmission Timeout即逾時重傳時間;

關鍵點在于:逾時和重傳間隔的政策,即怎樣确定逾時間隔和重傳間隔;

  TCP中的四個定時器:2MSL定時器;重傳定時器;堅持定時器;保活定時器;

首先是如何得到RTO值;(假設已經能測量到RTT值情況下)

  RTO值是依賴RTT值來确定的;而鑒于網絡環境的不穩定性,RTT總是變化的,

  RTT = 0.1*M  + 0.9*R;  M:目前測試的RTT值,R:曆史RTT的值;

  RTO=@RTT;        @:一般取2;

詳解過程參見RFC793,但是該方法是有缺陷的;

新的方法:

  Err = M - A;  M:目前RTT值, A:曆史RTT值;

  平均值:A = A+gErr;  A:曆史RTT值, g:常量, 

  方差:D = D + h(|Err| - D); D:曆史D的值,h:常量

 (重點):RTO = A + 4D;

RTO的初始化: A=0; D=3;(即沒有測的RTT情況下)

當資料正常傳輸的情況下,我們就會用上面的公式來更新各個資料,并重開定時器,來保證下一個資料被順利傳輸。要注意的是:重傳的情況下,RTO不用上面的公式計算,而采用一種叫做“指數退避”的方式。例如:當RTO為1S的情況下,發生了資料重傳,我們就用RTO=2S的定時器來重新傳輸資料,下一次用4S。一直增加到64S為止。

(也就是說:1、計時器計算是否逾時是用的是幾乎時時更新的RTO(估計器)時間,而重傳時間間隔采用的是“指數退避(exponential backoff)“時間,

      2、并且在重傳的情況下,不更新估計器的各種參數,

上述兩點就是所謂的 Karn算法

);

估計器的更新:

一個連接配接中,有且僅有一個測量定時器被使用。也就是說,如果TCP連續發出3組資料,隻有一組資料會被測量。

ACK資料報不會被測量,原因很簡單,沒有ACK的ACK回應可以供結束定時器測量

示例: 

 1、傳SYN:

    傳輸初始SYN所使用的RTO:RTO = A + 2D = 6s; (這個公式以後不再用了)

  2、上述SYN丢失了;然後逾時了;因為6s内沒有收到ACK;

    計算目前的RTO: RTO=A + 4D = 0 + 4×3 = 12s

  由于這是第一次逾時,我們使用的倍數是2^0;RTO = 2^0*12 = 12s

擁塞避免算法與慢啟動算法的結合:

  原因:資料在傳輸的時候不能隻使用一個視窗協定,我們還需要有一個擁塞視窗來控制資料的流量,使得資料不會一下子都跑到網路中引起“擁塞”。曾經提到過,擁塞視窗最初使用指數增長的速度來增加自身的視窗,直到發生逾時重傳,再進行一次微調。但是沒有提到,如何進行微調,擁塞避免算法和慢啟動門限就是為此而生。

  擁塞避免算法和慢啟動算法需要對每個連接配接維持兩個變量:

    一個擁塞視窗cwnd,  和 一個慢啟動門限ssthresh;它們的工作過程如下:

  1、對一個給定的連接配接,初始化cwnd為1個封包段,ssthresh為2^16=65535個位元組;

  2、此時TCP輸出的封包段不能超過cwnd和接收方通告視窗的大小,擁塞避免是c方使用的流量控制,通告視窗則是s方進行的流量控制,

    擁塞避免是c方感受到網絡擁塞的估計;通告視窗與s方在該連接配接上的緩存大小有關;

  3、當擁塞發生時(逾時或者收到重複的ACK;都表明丢包了), ssthresh被設定為目前視窗大小的一半(目前視窗即cwnd和通告視窗兩者中的小值,但最少為2個封包段),

    如果是逾時引起的擁塞,則cwnd被設定為1個封包段(這就是慢啟動)

  4、當新的資料被對方确認時,就增加cwnd,但增加的方法依賴于我們是否正在進行慢啟 動或擁塞避免。如果cwnd小于或等于ssthresh,則正在進行慢啟動,否則正在進行擁塞避免。 慢啟動一直持續到    我們回到當擁塞發生時所處位置的半時候才停止(因為我們記錄了在步驟2 中給我們制造麻煩的視窗大小的一半),然後轉為執行擁塞避免。

這是資料丢包的情況下給出的一種修補機制。一般來說,重傳發生在逾時之後,但是如果發送端接受到3個以上的重複ACK的情況下,就應該意識到,資料丢了,需要重新傳遞。這個機制是不需要等到重傳定時器溢出的,是以叫做快速重傳,而重新傳遞以後,因為走的不是慢啟動而是擁塞避免算法,是以這又叫做快速恢複算法。流程如下:

當收到第3個重複的ACK時,将ssthresh設定為目前擁塞視窗cwnd的一半。重傳丢失的 封包段。設定cwnd為ssthresh加上3倍的封包段大小。

每次收到另一個重複的ACK時, cwnd增加1個封包段大小并發送1個分組(如果新的 cwnd允許發送)。

當下一個确認新資料的ACK到達時,設定cwnd為ssthresh(在第1步中設定的值)。這個 ACK應該是在進行重傳後的一個往返時間内對步驟1中重傳的确認。另外,這個ACK也應該 是對丢失的分組和收到的第1個重複的ACK之間的所有中間封包段的确認。這一步采用的是擁 塞避免,因為當分組丢失時我們将目前的速率減半

答案是:不會,TCP會堅持用自己的定時器,但是TCP會保留下ICMP的錯誤并且通知使用者。

TCP為了提高自己的效率,允許再重新傳輸的時候,隻要傳輸包含重傳資料封包的封包就可以,而不用隻重傳需要傳輸的封包。

  

繼續閱讀