nagle演算法和TCP NODELAY

2021-09-07 23:22:40 字數 1111 閱讀 8365

寫socket發現的乙個詭異現象,當時將多個小資料寫操作合併成乙個寫操作,問題就沒了。chenshuo同學還建議我設定tcp_nodelay,只是後來因為事情忙,也就沒有再深究下去。

現在大概明白,是由於nagle演算法在搗亂。

tcp/ip協議中,無論傳送多少資料,總是要在資料前面加上協議頭,同時,對方接收到資料,也需要傳送ack表示確認。為了盡可能的利用網路頻寬,tcp總是希望盡可能的傳送足夠大的資料。(乙個連線會設定mss引數,因此,tcp/ip希望每次都能夠以mss尺寸的資料塊來傳送資料)。

nagle演算法就是為了盡可能傳送大塊資料,避免網路中充斥著許多小資料塊。

nagle演算法的基本定義是任意時刻,最多只能有乙個未被確認的小段。所謂「小段」,指的是小於mss尺寸的資料塊,所謂「未被確認」,是指乙個資料塊傳送出去後,沒有收到對方傳送的ack確認該資料已收到。

舉個例子,比如之前的blog中的實驗,一開始client端呼叫socket的write操作將乙個int型資料(稱為a塊)寫入到網路中,由於此時連線是空閒的(也就是說還沒有未被確認的小段),因此這個int型資料會被馬上發送到server端,接著,client端又呼叫write操作寫入『/r/n』(簡稱b塊),這個時候,a塊的ack沒有返回,所以可以認為已經存在了乙個未被確認的小段,所以b塊沒有立即被傳送,一直等待a塊的ack收到(大概40ms之後),b塊才被傳送。整個過程如圖所示:

這裡還隱藏了乙個問題,就是a塊資料的ack為什麼40ms之後才收到?這是因為tcp/ip中不僅僅有nagle演算法,還有乙個ack延遲機制。當server端收到資料之後,它並不會馬上向client端傳送ack,而是會將ack的傳送延遲一段時間(假設為t),它希望在t時間內server端會向client端傳送應答資料,這樣ack就能夠和應答資料一起傳送,就像是應答資料捎帶著ack過去。在我之前的時間中,t大概就是40ms。這就解釋了為什麼'/r/n'(b塊)總是在a塊之後40ms才發出。

如果你覺著nagle演算法太搗亂了,那麼可以通過設定tcp_nodelay將其禁用。當然,更合理的方案還是應該使用一次大資料的寫操作,而不是多次小資料的寫操作。

from:

網路程式設計之nagle演算法和TCP NODELAY

之前寫過一篇blog 描述了用mina的時候寫socket發現的乙個詭異現象,當時將多個小資料寫操作合併成乙個寫操作,問題就沒了。chenshuo同學還建議我設定tcp nodelay,只是後來因為事情忙,也就沒有再深究下去。現在大概明白,是由於nagle演算法在搗亂。tcp ip協議中,無論傳送多...

Nagle演算法和延遲ACK

nagle演算法 是為了減少廣域網上的小分組的數目,從而減少網路擁塞的出現。該演算法要求乙個tcp連線上最多只能有乙個未被確認的未完成的小分組,在該分組ack到達之前不能傳送其他的小分組,tcp需要收集這些少量的分組,並在ack到來時以乙個分組的方式傳送出去,其中小分組的定義是小於mss的任何分組。...

延遲確認和Nagle演算法

前篇文章介紹了三次握手和四次揮手,了解了tcp是如何建立和斷開連線的,文末還提到了抓包揮手時的乙個 異常 現象,當時無法解釋,特地查了資料,知道了資料傳輸中的延遲確認策略。何謂延遲確認策略?正是這個策略,讓圖中缺少了一次斷開連線的包,仔細看可以發現4405和4287之間時間也是差了200ms左右,為...