TCP選項:TCP_NODELAY和TCP_CORK

Nagle算法 TCP_NODELAY和TCP_CORK

Nagle算法
根據創建者John Nagle命名。該算法用於對緩衝區內的一定數量的消息進行自動連接。該處理過程

(稱爲Nagling),通過減少必須發送的封包的數量,提高了網絡應用 程序系統的效率。Nagle算法

,由Ford Aerospace And Communications Corporation Congestion Control in IP/TCP

internetworks(IETF RFC 896)(1984)定義,最初是用於緩衝Ford的私有TCP/IP網絡擁塞情況,不

過被廣泛傳播開來。

Nagle的文檔定義了一種他稱之爲小封包問題的解決方法。當某個應用程序每次只產生一字節的數

據,就會導致網絡由於這樣的小封包而過載(該情況通 常被稱爲“發送端SB窗口併發症”),從

而產生該問題。一個源自鍵盤的單一字符-1字節的數據-可能導致一個41字節的封包被傳送,該

封包包含了1字節的 有用數據和40字節的頭部數據。這種4000%過載的情況,在像APRANET這樣只有

很輕負載的網絡中是可以接受的,但在像Ford這樣的負載很重的網 絡中,可能強制重傳,導致封

包丟失,並且通過過度擁擠交換節點和網關降低了傳播速度。更進一步,當連接被丟棄時,吞吐量

可能被降低。Nagle算法-通常 的實現方法是在一個TCP程序中插入兩行代碼-在發送方,對標識

爲沒有迴應的數據進行緩衝(存儲)(這句怪怪的,其實應該是對未發送數據按順序進行緩衝,在

發送時進行拼接)。順序發送的數據將被保持到接收到被標識數據的迴應或者一整包有價值的數據

需要被髮送。

雖然Nagle算法用於解決Ford網絡內產生的問題,但同樣的問題也出現在APRANet。通過網絡,

Nagling被廣泛實現,包括 internet,並且產生了巨大的效用-雖然某些時候在高交互性環境如一

些C/S情況下不希望進行該處理。在這種情況下,可以通過 TCP_NODELAY套接字選項關閉Nagling。

注:Nagle雖然解決了小封包問題,但也導致了較高的不可預測的延遲,同時降低了吞吐量。


實際上這就的你動手來自己實現以下Nagle算法了。實際上Nagle算法並不是很複雜,他的主要職責

是數據的累積,實際上有兩個門檻:一個就是緩 衝區中的字節數達到了一定量,另一個就是等待

了一定的時間(一般的Nagle算法都是等待200ms);這兩個門檻的任何一個達到都必須發送數據了

。一般 情況下,如果數據流量很大,第二個條件是永遠不會起作用的,但當發送小的數據包時,

第二個門檻就發揮作用了,防止數據被無限的緩存在緩衝區不是好事情哦。 瞭解了TCP的Nagle算

法的原理之後我們可以自己動手來實現一個類似的算法了,在動手之前我們還要記住一個重要的事

情,也是我們動手實現Nagle算 法的主要動機就是我想要緊急發送數據的時候就要發送了,所以對

於上面的兩個門檻之外還的增加一個門檻就是緊急數據發送。現在可以開始工作了,我們這裏主要

給出思路:

首先我們必須在SOCKET之上再建立一層,來定義我們的自己的傳輸控制,我們的Nagle算法也是在

這層裏面實現的。 
Disable哪個TCP的Nagle算法,都自己動手寫了,要它幹嗎 
使 用Select函數來查看是否可以發送數據,當然我們實質是否可寫的fd_set的時候需要加入我們

的三個門檻,首先是按照字節和緊急數據來檢查,一般情 況下這兩個條件就搞定了,然後再按照

時間來決定。我們可是使用一個累積字節記數器和一個等待時間計時器。累積字節記數器在每次添

加數據到我們的控制層的時 候就累加一下,發送完畢的時候減去響應的字節數;而計時器在第一

次將數據提交給控制層的時候啓動(可以使用Windows的GetTickcount來得 到當前的時間),然後

在每次發送數據完畢的時候重新復位一下。 
實際上這樣就已經實現了Nagle算法,而且不需要經常調用GetTickCount而降低了系統的性能。

TCP_CORK

TCP鏈接的過程中,默認開啓Nagle算法,進行小包發送的優化。優化網絡傳輸,兼顧網絡延時和網

絡擁塞。這個時候可以置位TCP_NODELAY關閉Nagle算法,有數據包的話直接發送保證網絡時效性。

在進行大量數據發送的時候可以置位TCP_CORK關閉Nagle算法保證網絡利用性。儘可能的進行數據

的組包,以最大mtu傳輸,如果發送的數據包大小過小則如果在0.6~0.8S範圍內都沒能組裝成一個

MTU時,直接發送。如果發送的數據包大小足夠間隔在0.45內時,每次組裝一個MTU進行發送。如果

間隔大於0.4~0.8S則,每過來一個數據包就直接發送。


下面摘自:http://blog.csdn.net/lin49940/archive/2009/07/26/4382303.aspx
TCP_NODELAY 選項

設置該選項: public void setTcpNoDelay(boolean on) throws SocketException 
讀取該選項: public boolean getTcpNoDelay() throws SocketException 
     默認情況下, 發送數據採用Negale 算法. Negale 算法是指發送方發送的數據不會立即發出,

而是先放在緩衝區, 等緩存區滿了再發出. 發送完一批數據後, 會等待接收方對這批數據的迴應,

然後再發送下一批數據. Negale 算法適用於發送方需要發送大批量數據, 並且接收方會及時作出

迴應的場合, 這種算法通過減少傳輸數據的次數來提高通信效率.

     如果發送方持續地發送小批量的數據, 並且接收方不一定會立即發送響應數據, 那麼Negale

算法會使發送方運行很慢. 對於GUI 程序, 如網絡遊戲程序(服務器需要實時跟蹤客戶端鼠標的移

動), 這個問題尤其突出. 客戶端鼠標位置改動的信息需要實時發送到服務器上, 由於Negale 算法

採用緩衝, 大大減低了實時響應速度, 導致客戶程序運行很慢.


下面摘自http://hi.baidu.com/dirlt/blog/item/5ea4be1795d30b03c83d6d7f.html

TCP_NODELAY和TCP_CORK

這裏瞭解一下問題的背景就好理解了[不考慮滑動窗口加入,只是說packet的組織]
1.歷史上TCP是每發送一次包等待一個ACK然後下一個

2.但是在一些交互式應用下比如Telnet,結果就是我們每按一次鍵就會發送一個packet.每一個字

符配一個TCP頭效率不高,那個Nagle算法出來了。發送方法送數據A時然後再等待接受方的ACK時,

積累本地收集到的所有TCP數據包然後一次性發送。但是很明顯Nagle算法不利於交互式情景

3.但是現代應用下面還是存在交互式應用的,所以有時候我們需要關閉Nagle那麼可以設置

TCP_NODELAY

4.但是Nagle組織包的長度是由系統決定的,有時候我們知道我們會每個1分鐘產生1字節,共1000

字節。如果完全由Nagle算法來發送的話,可能還是會1字節1字節發送[這是一種極端情況,假設返

回ACK時間不是很長]。這個時候首先設置TCP_CORK能夠阻塞住TCP[儘量阻塞住],等我們write完

1000字節之後,取消TCP_CORK,這個時候就能夠將1000字節一次發出
TCP_NODELAY和TCP_CORK都是禁用Nagle算法,只不過NODELAY完全關閉而TCP_CORK完全由自己決定

發送時機。Linux文檔上說兩者不要同時設置。

發佈了23 篇原創文章 · 獲贊 9 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章