1. 程式人生 > 實用技巧 >遇到的 超時重傳

遇到的 超時重傳

之前有一篇文章說到了RTTRTT__RTO

TCP使用一個重傳定時器來在缺少資料接收端反饋的情況下保證資料到達,這個定時器時間被稱為RTO(retrnasmission timeout)

從這個報文中可以看到:服務端的報文沒有被確認導致發生超時重傳

那要怎麼處理這個問題呢?

RTO基本演算法:https://tools.ietf.org/html/rfc6298 見rfc

協議中主要有兩種方法來計算RTO一種是RFC793的經典方法(classic method),另一種是RFC6298的標準方法(standard method)。

1、RTO計算及更新

為了計算當前的RTO,TCP傳送端維護兩個狀態變數一個是SRTT(smoothed round-trip time)一個是RTTVAR (round-trip time variation),另外還有一個TCP時鐘粒度G。

  • 1)、在沒有測量到有效的RTT取樣之前,設定RTO=1s;

  • 2)、在第一個有效的RTT取樣測量出來後,假設取樣值為R,則進行如下初始化過程

srtt為經過平滑後的RTT值,它代表著當前的RTT值,每收到一個ACK更新一次。為了避免浮點運算,它是實際RTT值的8倍。

rttvar可升可降,代表著連線的抖動情況,在連線斷開前都有效。

SRTT = R

RTTVAR = R/2

RTO = SRTT + max(G,K*RTTVAR)

其中K = 4;

  • 3)、當隨後的RTT取樣R’測量到以後,按照如下更新:

RTTVAR = (1 - beta) * RTTVAR + beta * |SRTT - R'|

SRTT = (1 - alpha) * SRTT + alpha * R'

注意用於計算RTTVAR的公式中的SRTT是本次更新前的值,也就是說這兩個公式的計算順序不能顛倒。其中alpha=1/8、 beta=1/4,alpha和beta的選值允許計算機通過移位做除法的快速運算。

計算出SRTT和RTTVAR後,RTO仍舊按照如下更新:

RTO = SRTT + max (G, K*RTTVAR)

  • 4)、當RTO計算出來後,如果RTO小於1s,RTO則應該設定為1s。雖然給出的是1s的下限,但是協議允許使用更低的下限。

  • 5)、也可以對RTO設定一個上限,協議建議上限至少為60s。

關於上面的RTT取樣,協議要求使用karn演算法進行取樣,同時要求至少在一個RTT裡面取樣一次(除非因為karn演算法導致不可能在一個RTT裡面取樣一次)。協議指出對於每個TCP報文進行RTT取樣測量不一定會得到更好的RTT估計值。

參考:https://www.cnblogs.com/lshs/p/6038535.html

具體對錯就那樣吧。。。。

RTO定時器管理

  • 1)、每次一個包含資料的TCP報文傳送出去的時候(包括重傳),如果RTO定時器沒有執行,則重啟RTO定時器,並設定定時時間為RTO。

  • 2)、當所有發出的資料報文都被ACK後,關閉這個RTO定時器。

  • 3)、當一個新的ack number到達的時候(新的ack number是指ack了新資料),如果還有未被ACK的資料,則重啟RTO定時器,並設定定時時間為當前RTO。

當RTO定時器觸發的時候(即所設定的定時時間到達的時候)

  • 4)、在還沒有ACK的報文裡面重傳最早發出去的報文。

  • 5)、設定RTO = RTO * 2,這也就是我們經常說的指數回退。也可以和上面RTO更新過程一樣新增一個同樣的上限來限制RTO大小。

  • 6)、重啟RTO定時器,設定定時時間為RTO(這裡的RTO是已經回退過的RTO)。

  • 7)、如果RTO定時器是因為等待SYN報文的ACK而超時,如果實現上使用的RTO值小於3s,這個RTO定時器必須被重新初始化為3s。

    在重傳完成後,新的RTT取樣可能會將RTO設定為與原來比較接近的值,從而消除指數回退對於RTO的影響。另外在多次指數回退過程中,TCP實現可能會清空SRTT和RTTVAR的值,一旦這兩個被清空,則需要使用上面RTO計算及更新中的第2)步來初始化SRTT和RTTVAR。

/* 最大RTO為120s,退避時不能超過這個值 */
#define TCP_RTO_MAX    ((unsigned)(120*HZ))
/* 最小RTO為200ms,rttvar不能低於這個值 */ 
#define TCP_RTO_MIN    ((unsigned)(HZ/5))
/* 初始RTO為1s */
#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ))    /* RFC6298 2.1 initial RTO value    */
#define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ))    /* RFC 1122 initial RTO value, now
                         * used as a fallback RTO for the
                         * initial data transmission if no
                         * valid RTT sample has been acquired,
                         * most likely due to retrans in 3WHS.
                         */

回到正題:現在已經丟包了,怎麼解決能讓他不丟包,客戶端那邊是儀器,也只能調整服務端了!!

修改RTO貌似不可能

那隻能修改重傳次數&&超時重傳最大時間??