TCP/IP学习笔记(六)Nagle算法
在TCP傳輸數據流中,存在兩種類型的TCP報文段,一種包含成塊數據(通常是滿長度的,攜帶一個報文段最多容納的字節數),另一種則包含交互數據(通常只有攜帶幾個字節數據)。
對于成塊數據的報文段,TCP采用正常的流程發送即可,因為數據利用率很高。而對于交互數據的報文段,數據利用率就顯得很低,在網絡環境不好的情況下容易加重網絡負擔。所以TCP必須對交互數據單獨處理
交互數據實際上就是字節數很少的數據,比如客戶端調用10次send操作,每次只發送一個字節的數據。
Nagle算法
nagle算法用于處理小報文段(微小分組)的發送問題
nagle算法的核心思想是允許網絡中最多只能有一個小分組被發送,而待發送的其它小分組會被重新分組成一個”較大的”小分組,等收到上一個小分組的應答后再發送
nagle算法可以減少網絡中微小分組的數量,比如客戶端需要依次向服務器發送大小為1,2,3,1,2字節的5個分組
在沒有開啟nagle算法的情況下,這些小分組會被依次發送(不需要等待上一個小分組的應答,因為沒啟動nagle),總共發送的報文段(分組)個數為5
當開啟nagle算法時,客戶端首先發送大小為1字節的第一個分組,隨后其它分組到達發送緩沖區,由于上一個分組的應答還沒有收到,所以TCP會先緩存新來的這4個小分組,并將其重新分組,組成一個大小為8(2+3+1+2)字節的”較大的”小分組。當第一個小分組的應答收到后,客戶端將這個8字節的分組發送。總共發送的報文段(分組)個數為2
可以看到,當傳輸數據存在大量交互數據時,nagle算法可以有效減少網絡中的報文段個數
下面通過wireshark抓包分析nagle算法,客戶端服務器的執行流程為
- 建立連接
- 客戶端將字符串”hello”發送給服務器,但是每次只發送一個字節(即連續調用5次send/write函數)
- 服務器收到客戶端的數據后將其緩存,等到全部收到后將其發回客戶端
- 通過wireshark觀察網絡中報文段的傳輸
不知道是操作問題還是客戶端服務器處在一個主機上傳輸速度太快的原因,代碼執行了好多次才有個別能體現nagle算法的結果
對圖中結果進行分析
- 1-3行是三次握手
- 4-5行是發送字節’h’以及服務器的應答
- 6-7行是發送字節’e’以及服務器的應答
- 8-9行是發送字節’llo’以及服務器的應答
- 10行是服務器發送的”hello”報文段
- 11-14行是四次揮手
可以看到nagle算法確實將待發送的小分組重新分組,等到上一個小分組確認報文到達后一起發送
禁止Nagle
雖然nagle算法可以減少網絡中小分組的個數,但是對于那些需要實時預覽的通訊程序而言,客戶端可能需要不斷發送更新數據并得到服務器的響應,這種情況下nagle算法會造成客戶端明顯的延遲,所以需要禁用nagle算法
將套接字描述符設置TCP_NODELAY選項可以禁止nagle算法
#include <netinet/tcp.h> ...void cancel_nagle(int fd) {int val = 1;::setsockopt(fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val)); }還是以上面的程序為例,這回將nagle算法禁止,觀察wireshark抓包結果,預計客戶端TCP可以連續發送小報文段而不需要等待上一個小報文段的確認
總結
以上是生活随笔為你收集整理的TCP/IP学习笔记(六)Nagle算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----计算整
- 下一篇: 每天一道LeetCode----从数组中