TCP協議是一種面向連接的可靠的傳輸層協議,它保證了數據的可靠傳輸,對於一些出錯、超時丟包等問題TCP設計了超時重傳機制,其基本原理:在發送一個數據之后,就開啟一個定時器,若是在這個時間內沒有收到發送數據的ACK確認報文,則對該報文進行重傳,在達到一定次數還沒有成功時放棄並發送一個復位信號。
1、超時重傳時間
RTO(Retransmission TimeOut),影響超時重傳機制協議效率的一個關鍵參數是重傳超時時間RTO,RTO的值被設置過大過小都會對協議造成不利影響。如果RTO設置過大將會使發送端經過較長時間的等待才能發現報文段丟失,降低了連接數據傳輸的吞吐量;另一方面,若RTO過小,發送端盡管可以很快地檢測出報文段的丟失,但也可能將一些延遲大的報文段誤認為是丟失,造成不必要的重傳,浪費了網絡資源。
如果底層網絡的傳輸特性是可預知的,那么重傳機制的設計相對簡單得多,可根據底層網絡的傳輸時延的特性選擇一個合適的RTO,使協議的性能得到優化。但是TCP的底層網絡環境是一個完全異構的互聯結構。在實現端到端的通信時,不同端點之間傳輸通路的性能可能存在着巨大的差異,而且同一個TCP連接在不同的時間段上,也會由於不同的網絡狀態具有不同的傳輸時延。
因次,TCP協議必須適應兩個方面的時延差異:一個是達到不同目的端的時延的差異,另一個是統一連接上的傳輸時延隨業務量負載的變化而出現的差異。為了處理這種底層網絡傳輸特性的差異性和變化性,TCP的重傳機制相對於其他協議顯然也將更為復雜,其復雜性主要表現在對超時時間間隔的處理上。為此,TCP協議使用自適應算法(Adaptive Retransmission Algorithm)以適應互聯網分組傳輸時延的變化。這種算法的基本要點是TCP監視每個連接的性能(即傳輸時延),由此每一個TCP連接推算出合適的RTO值,當連接時延性能變化時,TCP也能夠相應地自動修改RTO的設定,以適應這種網絡的變化。
RTO一般是根據RTT來設置的。若 RTO 小於 RTT,則會造成很多不必要的重傳;若 RTO 遠大於 RTT,則會降低整體網絡利用率,RTO 是保證 TCP 性能的關鍵。並且不同連接的RTT不相同,同一個連接不同時間的 RTT 也不相同,所以 RTO 的設置一直都是研究熱點。
2、連接往返時間
RTT(Round Trip Time),對一個連接而言,若能夠了解端點間的傳輸往返時間,則可根據RTT來設置一合適的RTO。顯然,在任何時刻連接的RTT都是隨機的,無法事先預知。TCP通過測量來獲得連接當前RTT的一個估計值,並以該RTT估計值為基准來設置當前的RTO。自適應重傳算法的關鍵就在於對當前RTT的准確估計,以便適時調整RTO。
為了搜集足夠的數據來精確地估算當前的RTT,TCP對每個報文都記錄下發送出的時間和收到的確認時間。每一個(發送時間,確認時間)對就可以計算出一個RTT測量值的樣本(Sample RTT)。TCP為每一個活動的連接都維護一個當前的RTT估計值。該值是對已經過去的一個時間段內該連接的RTT了兩只的加權平均,並作為TCP對連接當前實際的RTT值的一種估計。RTT估計值將在發送報文段時被用於確定報文段的RTO。為了保證它能夠比較准確地反應當前的網絡狀態,每當TCP通過測量獲得了個新的RTT樣本時,都將對RTT的估計值進行更新。不同的更新算法或參數可能獲得不同的特性。
2.1、RTT的精確估值測量--Karn算法
如果在一個報文段中的數據被一次性地成功傳輸和確認,那么發送端可以准確得到該報文段傳輸的RTT樣本。但若出現了重傳,情況就會變得很復雜。例如,一個報文段發送后出現超時,TCP將在另一個報文段中重傳。由於這兩個報文段包含了同樣的數據,發送方接收到確認信息時將無法分辨出確認信息到底是針對哪個報文段的,因為這兩個報文段產生的確認信息可能是完全相同的,確認信息既可能是針對原始報文段的(這種情況可能是由於原報文段或確認在傳輸中被延遲造成的),也可能是對重傳報文段的確認。這種現象稱為確認二義性(Acknowledgement Ambiguiity)。確認的二義性將導致TCP無法准確地估算RTT。
為了避免確認二義性帶來的問題,TCP采用了Karn算法來維護RTT的估計值。
Karn算法規定,TCP只能利用沒有確認二義性(既無重發、一次發送成功並得到確認的報文段)的RTT樣本來對RTT的估計值進行調整。
3、重傳
3.1、重傳時發送數據的大小
數據在傳輸的時候不能只使用一個窗口協議,還需要有一個
擁塞窗口來控制數據的流量,使得數據不會一下子都跑到網路中引起“擁塞”。
擁塞窗口最初使用指數增長的速度來增加自身的窗口,直到發生超時重傳,再進行一次微調。但是如何進行微調,擁塞避免算法和慢啟動門限就是為此而生。
所謂的慢啟動門限就是說,當
擁塞窗口超過這個門限的時候,就使用擁塞避免算法,而在門限以內就采用慢啟動算法。所以這個標准才叫做門限,通常,擁塞窗口記做cwnd,慢啟動門限記做ssthresh。下面來看看擁塞避免和慢啟動是怎么一起工作的。
3.2、算法概要
對一個給定的連接,初始化cwnd為1個報文段,ssthresh為65535個字節。TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小。擁塞避免是發送方使用的
流量控制,而通告窗口則是接收方進行的流量控制。前者是發送方感受到的
網絡擁塞的估 計,而后者則與接收方在該連接上的可用
緩存大小有關。當擁塞發生時(超時或收到重復確認),ssthresh被設置為當前窗口大小的一半(cwnd 和接收方通告窗口大小的最小值,但最少為2個報文段)。此外,如果是超時引起了擁塞,則 cwnd被設置為1個報文段(這就是慢啟動)。當新的數據被對方確認時,就增加cwnd,但增加的方法依賴於是否正在進行慢啟動或擁塞避免。如果cwnd小於或等於ssthresh,則正在進行慢啟動,否則正在進行擁塞避免。慢啟動一直持續到回到當擁塞發生時所處位置的半時候才停止(因為記錄了在步驟2 中制造麻煩的窗口大小的一半),然后轉為執行擁塞避免。
3.3、快速重傳和快速恢復算法
這是數據
丟包的情況下給出的一種修補機制。一般來說,重傳發生在超時之后,但是如果發送端接受到3個以上的重復ACK的情況下,就應該意識到,數據丟了,需要重新傳遞。這個機制是不需要等到重傳定時器溢出的,所以叫做快速重傳,它可以避免發送端因等待重傳計時器的超時而空閑較長時間,以此增加網絡吞吐量。而重新傳遞以后,因為走的不是慢啟動而是擁塞避免算法,所以這又叫做快速恢復算法。流程如下:
當收到第3個重復的ACK時,將ssthresh設置為當前
擁塞窗口cwnd的一半。重傳丟失的
報文段。設置cwnd為ssthresh加上3倍的
報文段大小。每次收到另一個重復的ACK時, cwnd增加1個
報文段大小並發送1個分組(如果新的 cwnd允許發送)。當下一個確認新數據的ACK到達時,設置cwnd為ssthresh(在第1步中設置的值)。這個 ACK應該是在進行重傳后的一個往返時間內對步驟1中重傳的確認。另外,這個ACK也應該是對丟失的分組和收到的第1個重復的ACK之間的所有中間
報文段 的確認。這一步采用的是擁塞避免。ICMP不會引起重新傳遞,TCP會堅持用自己的定時器,但是TCP會保留下ICMP的錯誤並且通知用戶。
3.4、重新分組
TCP為了提高自己的效率,允許再重新傳輸的時候,只要傳輸包含重傳數據
報文的報文就可以,而不用只重傳需要傳輸的報文。