在使用一些协议通讯的时候,比如Telnet,会有一个字节字节的发送的情景,每次发送一个字节的有用数据,就会产生41个字节长的分组,20个字节的IP Header 和 20个字节的TCP Header,这就导致了1个字节的有用信息要浪费掉40个字节的头部信息,这是一笔巨大的字节开销,而且这种Small packet在广域网上会增加拥塞的出现。

如果解决这种问题? Nagle就提出了一种通过减少需要通过网络发送包的数量来提高TCP/IP传输的效率,这就是Nagle算法

Nagle算法

Nagle算法主要是避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。相反,TCP收集这些少量的小分组,并在确认到来时以一个分组的方式发出去。

  1. if there is new data to send
  2. if the window size >= MSS and available data is >= MSS
  3. send complete MSS segment now
  4. else
  5. if there is unconfirmed data still in the pipe
  6. enqueue data in the buffer until an acknowledge is received
  7. else
  8. send data immediately
  9. end if
  10. end if
  11. end if

从上述算法中看出:

1. 对于MSS的片段直接发送

2. 如果有没有被确认的data在缓冲区内,先将待发送的数据放到buffer中直到被发送的数据被确认【最多只能有一个未被确认的小分组

3. 两种情况置位,就直接发送数据,实际上如果小包,但是没有未被确认的分组,就直接发送数据。

这里通过一个实验来看下Nagle算法对于发送的优化:

实验要求:Client端每次发送1个字节,将hello发送到Server端,然后server再全部发送给Client,其实要点在于Client的发送,预期的结果是:

1. 我们虽然一个字节一个字节的发,但是在协议中使用Nagle算法,可能会有延时等待的状况,即将几个字符合成一个片段进行发送

2. 必须是收到对方的确认之后,才能再次发送

看下实验的结果:

从图中的结果可以看出

1. HELLO 被分成 2个包发送了,应用层调用send 5次,由于Nagle算法,将ELLO合成一个包发送,这样大可以减少Samll packet的数量,增加TCP传输的效率

2. 分成的2个数据包,并没有连续被发出,这也符合Nagle算法的原则,即TCP连接上最多只能有一个未被确认的小分组,等待收到ACK之后,才发第二个封包。

禁用Nagle算法

在默认的情况下,Nagle算法是默认开启的,Nagle算法比较适用于发送方发送大批量的小数据,并且接收方作出及时回应的场合,这样可以降低包的传输个数。同时协议也要求提供一个方法给上层来禁止掉Nagle算法

当你的应用不是连续请求+应答的模型的时候,而是需要实时的单项的发送数据并及时获取响应,这种case就明显不太适合Nagle算法,明显有delay的。

linux提供了TCP_NODELAY的选项来禁用Nagle算法。

禁用方法:

  1. setsockopt(client_fd, SOL_TCP, TCP_NODELAY,(int[]){1}, sizeof(int));

来看下禁用后同样发送Hello的实验结果

从实验结果中可以得出如下结论:

1. 禁止Nagle算法,每一次send,都会组一个包进行发送,HELLO被分成5个小包分别发送

2.不用等待ACK,可以连续发送

Delay ACK and Nagle

Nagle指出Nagle算法与Delay ACK机制有共存的情况下会有一些非常糟糕的状况,比如举一个场景:PC1和PC2进行通信,PC1发数据给PC2,PC1使用Nagle算法,PC2有delay ACK机制

1. PC1发送一个数据包给PC2,PC2会先不回应,delay ACK

2. PC1再次调用send函数发送小于MSS的数据,这些数据会被保存到Buffer中,等待ACK,才能再次被发送

从上面的描述看,显然已经死锁了,PC1在等待ACK,PC2在delay ACK,那么解锁的代价就是Delay ACK的Timer到期,至少40ms[40ms~500ms不等],也就是2种算法在通信的时候,会产生不必要的延时!

可以看下实验的图示, 9包是发送H字符到server,可以看到隔了30ms的delay ack延时才等到数据,发送一个DATA+ACK包,在这个时间段内其实也是用包发送的,但是nagle算法是要等待ACK的到来才能发包的,所以也会看到11号包要在ACK包之后。如果30ms延时仍然没有数据,就是我们上述说的那样白白的等待一个delay ack超时。

如何来解决这种问题?

其实Nagle算法本身的立意是好的,避免网络充斥着过多的小包,提高网络传输的效率,同时Delay ACK也是为了提高TCP的性能,不过二者遇到了,就比较悲剧了。其实在RFC中已经提供了一个用户级别的解决方案,即避免 write--write--read的这种写法,write--read--write--read 以及write--write--write都是OK的。假设这里有数据要发送,这个数据分为头部和数据部分,2部分发送,然后再回读响应,写法如下

1.write(header)

2.write(body)

3.read(response)

服务器read写法如下

1. read(request)

2. process(request)

3. write(response)

应用程序使能了Nagle算法,第一个header是一定能够发送出去的,因为前面没有带确认的数据,服务器端接收到header之后,也发现是不完全的,还会再次等待request,同时要delay ACK,再次发write的时候,发现没有ACK,也会等待ACK延迟发送。这样只能超时才能再次传输。

这个问题的产生,主要是Nagle和delay ACK 副作用以及write write read的程式造成的。一般写程序的时候不推荐这样的写法。如何解决? 可能想到的就是上面的禁止掉Nagle算法,这也是一种办法,不过这种办法同时也会让网络充斥小包,降低效率。对于应用程序来讲,只要避免write-wirte-read的这种写法就可以避免掉问题,比如write一块去写,一次写成功,就一个包发过去了,就没有等待delay的过程了!所以写程序的时候还是要注意再注意。

TCP-IP详解:Nagle算法的更多相关文章

  1. TCP/IP详解 (转)

    TCP/IP详解学习笔记(1)-基本概念 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中 ...

  2. TCP IP详解(转)

    大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 网络七层协议简称OSI.TCP/IP刨除了物理层,并把上三层(会话层.表示层和应用层)统称 ...

  3. 《TCP/IP详解卷1:协议》第19章 TCP的交互数据流-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  4. TCP/IP详解学习笔记 这位仁兄写得太好了

      TCP/IP详解学习笔记(1)-基本概念 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣 ...

  5. TCP/IP详解学习笔记 这位仁兄写得太好了.(转载)

    TCP/IP详解学习笔记   这位仁兄写得太好了   TCP/IP详解学习笔记   这位仁兄写得太好了. http://blog.csdn.net/goodboy1881/category/20444 ...

  6. 【转】TCP/IP详解学习笔记(二)

    TCP/IP详解学习笔记(5)-IP选路,动态选路,和一些细节 1.静态IP选路 1.1.一个简单的路由表 选路是IP层最重要的一个功能之一.前面的部分已经简单的讲过路由器是通过何种规则来根据IP数据 ...

  7. 《TCP/IP详解:卷一》-TCP部分讲解

    TCP/IP协议 作者:Danbo 2015-7-2 本文为参考TCP/IP详解卷一,某些知识点加上了作者自己的理解,如有错误,欢迎指正,可以微博联系我! TCP包格式和IP包格式如下: TCP的正常 ...

  8. 《TCP/IP详解卷1:协议》第3章 IP:网际协议(1)-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  9. 《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

  10. 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记

    章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...

随机推荐

  1. ACM题目————A Knight's Journey

    Description BackgroundThe knight is getting bored of seeing the same black and white squares again a ...

  2. SNMP学习笔记之SNMPv3的报文格式以及基于USM的认证和加密过程

    下面我们就主要讲解SNMPv3的报文格式以及基于USM的认证和加密过程! 1.SNMPv3的消息格式 如下图1: 图 1 其中,整个SNMPv3消息可以使用认证机制,并对EngineID.Contex ...

  3. Python Web学习笔记之递归和迭代的区别

    电影故事例证:迭代——<明日边缘>递归——<盗梦空间> 迭代是更新变量的旧值.递归是在函数内部调用自身. 迭代是将输出做为输入,再次进行处理.比如将摄像头对着显示器:比如镜子对 ...

  4. Jsoup简介

    Jsoup简介 一.概述 Jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来 ...

  5. Intel RDT

    首先 spec, 从671页看起 https://software.intel.com/sites/default/files/managed/a4/60/325384-sdm-vol-3abcd.p ...

  6. Python3基础 input 输入浮点数,整数,字符串

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  7. 【传输对象】kafka传递实体类消息

    工具类 负责对象字节数组的相互转换,传输数据用 package com.yq.utils; import java.io.ByteArrayInputStream; import java.io.By ...

  8. 第十一章 非对称加密算法--DH

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 11.1.非对称加密算法 特点: 发送方和接收方均有一个密钥对(公钥+私钥),其中公 ...

  9. AtCoder Tenka1 Programmer Beginner Contest 解题报告

    赛时写了ABC,D实在没啥思路,然后C又难调...然后就从写完AB时的32名掉到了150+名 T_T 码力不够,思维不行,我还是AFO吧 比赛链接 A - Measure sb模拟,奇数串倒着输出偶数 ...

  10. DBMS 数据库管理系统 DataBase Management System