1. 程式人生 > >TCP Nagle演算法以及延遲確認(即延遲迴復ACK)的學習

TCP Nagle演算法以及延遲確認(即延遲迴復ACK)的學習

TCP/IP協議中,無論傳送多少資料,總是要在資料前面加上協議頭,同時,對方接收到資料,也需要傳送ACK表示確認。為了儘可能的利用網路頻寬,TCP總是希望儘可能的傳送足夠大的資料。

一個連TCP接會設定MSS引數,因此,TCP/IP希望每次都能夠以MSS尺寸的資料塊來發送資料)。

Nagle演算法就是為了儘可能傳送大塊資料,避免網路中充斥著許多小資料塊。(尤其在廣域網中)(減少大量小包的傳送)

 

Nagle演算法的基本定義是任意時刻,最多隻能有一個未被確認的小段。所謂“小段”,指的是小於MSS尺寸的資料塊

所謂“未被確認”,是指一個數據塊傳送出去後,沒有收到對方傳送的ACK確認該資料已收到。

 

 

Nagle演算法的規則(可參考tcp_output.c檔案裡tcp_nagle_check函式註釋):

 

(1)如果包長度達到MSS,則允許傳送;

 

(2)如果該包含有FIN,則允許傳送;

 

(3)設定了TCP_NODELAY選項,則允許傳送;(即關閉了Nagle演算法了,可以立刻發

 

(4)未設定TCP_CORK選項時,若所有發出去的小資料包(包長度小於MSS)均被確認,則允許傳送;

 

(5)上述條件都未滿足,但發生了超時(一般為200ms),則立即傳送。

 

Nagle演算法只允許一個未被ACK的包存在於網路,它並不管包的大小,因此它事實上就是一個擴充套件的停-等協議(停止等待ARQ協議),只不過它是基於包停-等的,而不是基於位元組停-等的。Nagle演算法完全由TCP協議的ACK機制決定,這會帶來一些問題,比如如果對端ACK回覆很快的話,Nagle事實上不會拼接太多的資料包,雖然避免了網路擁塞,網路總體的利用率依然很低。  好好理解這句話  就是如果ack回覆的快   Nagle演算法並不會來得急拼多大的包   雖然避免了網路擁塞,網路總體的利用率依然很低

 

 

 

 

TCP_NODELAY 套接字選項

 

預設情況下,傳送資料採用Negle 演算法。這樣雖然提高了網路吞吐量,但是實時性卻降低了,在一些互動性很強的應用程式來說是不允許的

 

使用TCP_NODELAY選項可以禁止Negale 演算法。 

 

 

 

 

延遲確認機制(TCP delayed acknowledgment)

 

全名Delayed Acknowledgment,簡稱延遲ACK,翻譯為延遲確認。 

 

與Nagle演算法一樣,延遲ACK的目的也是為了減少網路中傳輸大量的小報文數,但該報文數是針對ACK報文的。 

 

一個來自發送端的報文到達接收端,TCP會延遲ACK的傳送,希望應用程式會對剛剛收到的資料進行應答,   這樣就可以用新資料將ACK捎帶過去。  (就是對請求應答的時候稍帶上ack,不單獨進行確認 就是這個意思咯) 

 

 

 

                                           下面是討論的重點!!!!!!

當Nagle演算法遇到Delayed ACK

在一個有資料傳輸的TCP連線中,如果只有資料傳送方啟用Nagle演算法,在其連續傳送多個小報文時,Nagle演算法機制會減少網路中的小報文數量。這就意味著,同樣傳輸相同大小的應用資料,在網路上的報文個數卻不同。 

 

舉個例子,傳送端需要連續傳送5個寫操作(應用程式將資料寫入到緩衝池的動作)的小報文,首先發送第一個,由於Nagle演算法的作用,在未收到第一個報文確認前傳送端在等待寫操作的同時進行讀操作,接收端並未啟用延遲確認(視TCP delay ACK時間為0),儘管剛收到該報文就發出確認,但由於網路延時的原因,在收集齊另外4個小報文後,傳送方才收到了第一個報文的ACK,則後面的4個報文會一起傳送出去(大小未超過MSS),接收端再次ACK。

在上述傳送5個小報文的過程中,只用了4個報文就實現了。

如果傳送端未啟用Nagle演算法,完成整個過程則至少需要8個報文或10個報文才能實現,這裡接收端未啟用延遲確認,如下圖所示。啟用Nagle演算法和未啟用Nagle演算法的場景中,從完成資料傳送的時間來看,未啟用Nagle演算法的方式花費的時間會更長一些,(也不一定吧個人覺得 還是要看網路環境  理論上是這樣)  如下圖所示。這裡基本看到了Nagle演算法的好處了。

還是上述資料傳輸場景,傳送端未啟用Nagle演算法,但接收端延遲確認預設時間為200ms,來看看這時的情況。 RFC 1122規定,Delayed ACK對單個的小報文可以延長確認的時間,但不允許有兩個連續的小報文不被確認。所以,當傳送端連續傳送兩個報文後,接收端必須給予確認。這時的資料傳輸情況如下圖,只有當第5個報文到達後,接收端由於延遲確認機制,會導致200ms的延時存在。

接下來看看,當Nagle演算法遇到Delayed ACK時會是什麼情況按照常理推斷,兩種深思熟慮的功能設計,應該是1+1>2的效果。具體如何,還是請事實說話

先繼續看上面的假設場景,該場景要求傳送端向接收端傳送5個連續的寫操作資料,但網路延時較大,同時傳送端啟用Nagle演算法,接收端Delayed ACK預設為200ms。 

傳送方先發出一個小報文,接收端收到後,由於延遲確認的機制,等待發送方的下一個報文到達。而傳送方由於Nagle演算法機制,在未接收到第一個報文的確認前,不會發送已讀取到的報文。  在這種場景下,暫不考慮應用處理時間,完成整個資料傳輸所需時間為2RTT+400ms,貌似情況不是特別糟糕。

如果上述其他條件不變,傳送方應用寫操作延時稍微變大,或傳送端的應用操作延時稍大,我們再看看,完成這個操作的延時情況。 

傳送方先發出一個小報文,接收端收到後,由於延遲確認的機制,等待發送方的下一個報文到達。由於傳送方應用資料寫操作延時較大,在經過RTT+200ms後,讀取到了下一個需要傳送的內容,此時接收到了第一個報文的確認,而網路中未有沒被確認的報文,傳送方需要再將第二個小報文傳送出去,以此類推,直到最後一個小報文被髮送,且接收到該報文的確認,此時整個資料傳輸過程完成。 

在這種情景下,完成整個資料傳輸所需時間則為5RTT+5*200ms,明顯增大了不少。如果相同情境下,有成千上萬的小報文傳送,則整體使用時間相當可觀了。

在實際情況下,如果傳送方程式做了一系列的寫、寫、讀操作的現象,這樣的操作都會觸發Nagle和延遲ACK演算法之間的互動作用,應該儘量避免