TCP/IP協議中,無論發送多少數據,總是要在數據前面加上協議頭,同時,對方接收到數據,也需要發送ACK表示確認。為了儘可能的利用網絡帶寬,TCP總是希望儘可能的發送足夠大的數據。(一個連接會設置MSS參數,因此,TCP/IP希望每次都能夠以MSS尺寸的數據塊來發送數據)。Nagle算法就是為了儘可能發送大塊數據,避免網絡中充斥着許多小數據塊。

一、Nagle算法的基本定義

任意時刻,最多隻能有一個未被確認的小段。

所謂“小段”,指的是小於MSS尺寸的數據塊,

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

二、Nagle算法的規則

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

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

(3)設置了TCP_NODELAY選項,則允許發送;

            TCP_NODELAY選項可以禁止Nagle 算法。

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

           設置該選項後,內核會盡力把小數據包拼接成一個大的數據包(一個MTU)再發送出去,當然若一定時間後(一般為200ms,該值尚待確認),內核仍然沒有組合成一個MTU時也必須發送現有的數據(不可能讓數據一直等待吧)。

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

三、 Nagle算法與CORK算法區別
  

  Nagle算法主要避免網絡因為太多的小包(協議頭的比例非常之大)而擁塞,而CORK算法則是為了提高網絡的利用率,使得總體上協議頭佔用的比例儘可能的小。如此看來這二者在避免發送小包上是一致的,

在用户控制的層面上,Nagle算法完全不受用户socket的控制,你只能簡單的設置TCP_NODELAY而禁用它,CORK算法同樣也是通過設置或者清除TCP_CORK使能或者禁用之,然而Nagle算法關心的是網絡擁塞問題,只要所有的ACK回來則發包,而CORK算法卻可以關心內容,在前後數據包發送間隔很短的前提下(很重要,否則內核會幫你將分散的包發出),即使你是分散發送多個小數據包,你也可以通過使能CORK算法將這些內容拼接在一個包內,如果此時用Nagle算法的話,則可能做不到這一點。

四、延遲確認

累積確認

有時候,發送方發送速度非常快,接收方一下下接收到了好幾個 tcp 段,可以通過累積確認的方式,一次確認好幾個 tcp 段,這樣減少報文段的傳輸。

捎帶確認

有時候,雙方互相發送數據,當接收到對方的 tcp 段後,先不着急確認,而是等待一會兒,連同數據和 ack 一起發送過去,這種情況叫捎帶確認。如果等了一會兒(到時間了),接收方還沒有數據要發送,那就直接回復一個純 ack 過去,這樣的 ack 稱為延時的 ack(Delayed ACK)。