1. Nagle算法:
是為了減少廣域網的小分組數目,從而減小網絡擁塞的出現;
該算法要求一個tcp連接上最多只能有一個未被確認的未完成的小分組,在該分組ack到達之前不能發送其他的小分組,tcp需要收集這些少量的分組,並在ack到來時以一個分組的方式發送出去;其中小分組的定義是小於MSS的任何分組;
該算法的優越之處在於它是自適應的,確認到達的越快,數據也就發哦送的越快;而在希望減少微小分組數目的低速廣域網上,則會發送更少的分組;
2. 延遲ACK:
如果tcp對每個數據包都發送一個ack確認,那么只是一個單獨的數據包為了發送一個ack代價比較高,所以tcp會延遲一段時間,如果這段時間內有數據發送到對端,則捎帶發送ack,如果在延遲ack定時器觸發時候,發現ack尚未發送,則立即單獨發送;
延遲ACK好處:
(1) 避免糊塗窗口綜合症;
(2) 發送數據的時候將ack捎帶發送,不必單獨發送ack;
(3) 如果延遲時間內有多個數據段到達,那么允許協議棧發送一個ack確認多個報文段;
3. 當Nagle遇上延遲ACK:
試想如下典型操作,寫-寫-讀,即通過多個寫小片數據向對端發送單個邏輯的操作,兩次寫數據長度小於MSS,當第一次寫數據到達對端后,對端延遲ack,不發送ack,而本端因為要發送的數據長度小於MSS,所以nagle算法起作用,數據並不會立即發送,而是等待對端發送的第一次數據確認ack;這樣的情況下,需要等待對端超時發送ack,然后本段才能發送第二次寫的數據,從而造成延遲;
4. 關閉Nagle算法:
使用TCP套接字選項TCP_NODELAY可以關閉套接字選項;
如下場景考慮關閉Nagle算法:
(1) 對端不向本端發送數據,並且對延時比較敏感的操作;這種操作沒法捎帶ack;
(2) 如上寫-寫-讀操作;對於此種情況,優先使用其他方式,而不是關閉Nagle算法:
--使用writev,而不是兩次調用write,單個writev調用會使tcp輸出一次而不是兩次,只產生一個tcp分節,這是首選方法;
--把兩次寫操作的數據復制到單個緩沖區,然后對緩沖區調用一次write;
--關閉Nagle算法,調用write兩次;有損於網絡,通常不考慮;
5. 禁止Nagle和開啟Nagle算法發送數據與確認示意圖:
