Nagle算法-

TCP缓冲区管理算法 · · 2370 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

说明:本文是最近项目上使用tcp时遇到的问题找到的原因,参考了网络上的几篇文章整理出来,如有版权问题,请留言。

   Nagle 算法用于对缓冲区内的一定数量的消息进行自动连接。该处理过程(称为Nagling),通过减少必须发送的封包的数量,提高了网络应用程序系统的效率。

**1. ** Nagle算法的规则


   (可参考tcp_output.c文件里tcp_nagle_check函数注释):

1)如果包长度达到MSS(MSS是最大分段大小Maxitum Segment Size ,MTU是最大传输单元Maxitum Transmission Unit),则允许发送;

2)如果该包含有FIN,则允许发送;

3)设置了TCP_NODELAY选项,则允许发送;

4)未设置TCP_CORK选项时,若所有发出去的包均被确认,或所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送。

   对于规则4),就是说一个TCP连接上最多只能有一个未被确认的小数据包,在该分组的确认到达之前,不能发送其他的小数据包。如果某个小分组的确认被延迟了,那么后续小分组的发送就会相应的延迟。也就是说延迟确认影响的并不只是被延迟确认的那个数据包,而是后续所有的应答包。

**2. ** Nagle算法 的门槛


    实际上Nagle算法并不是很复杂,他的主要职责是数据的累积,实际上有 三 个门槛:

1) 缓冲区中的字节数达到了一定量 ;

2) 等待了一定的时间(一般的Nagle算法都是等待200ms);

3) 紧急数据发送 。

    这 三 个门槛的任何一个达到都必须发送数据了。一般情况下,如果数据流量很大,第二个条件是永远不会起作用的,但当发送小的数据包时,第二个门槛就发挥作用了,防止数据被无限的缓存在缓冲区不是好事情哦。 

**3. ** Nagle算法的选项配置


    TCP_NODELAY和TCP_CORK都是禁用Nagle算法,只不过NODELAY完全关闭而TCP_CORK完全由自己决定发送时机。 Linux文档上说两者不要同时设置 。


**3.1 ** TCP_NODELAY 选项


设置该选项:  setsockopt(s,IPPRO_TCP,TCP_NODELAY,(const   char*)& on ,sizeof( int ));

读取该选项:  g etsockopt(s,IPPRO_TCP,TCP_NODELAY,(char*)& on , &optlen );   

  

    默认情况下, 发送数据采用N a gle 算法.  Nagle  算法是指发送方发送的数据不会立即发出,而是先放在缓冲区, 等缓存区满了再发出. 发送完一批数据后, 会等待接收方对这批数据的回应,然后再发送下一批数据 。  

    Nagle  算法适用于发送方需要发送大批量数据, 并且接收方会及时作出回应的场合, 这种算法通过减少传输数据的次数来提高通信效率 。

   如果发送方持续地发送小批量的数据, 并且接收方不一定会立即发送响应数据, 那么 Nagle 算法会使发送方运行很慢 。

3.2 TCP_CORK选项


    TCP链接的过程中,默认开启Nagle算法,进行小包发送的优化。优化网络传输,兼顾网络延时和网络拥塞。这个时候可以置位TCP_NODELAY关闭Nagle算法,有数据包的话直接发送保证网络时效性。

    在进行大量数据发送的时候可以置位TCP_CORK关闭Nagle算法保证网络利用性。尽可能的进行数据的组包,以最大mtu传输,如果发送的数据包大小过小则如果在0.60.8S范围内都没能组装成一个MTU时,直接发送。如果发送的数据包大小足够间隔在0.45内时,每次组装一个MTU进行发送。如果间隔大于0.40.8S则,每过来一个数据包就直接发送。

    Nagle组织包的长度是由系统决定的,有时候我们知道我们会每个1分钟产生1字节,共1000字节。如果完全由Nagle算法来发送的话,可能还是会1字节1字节发送[这是一种极端情况,假设返回ACK时间不是很长]。这个时候首先设置TCP_CORK能够阻塞住TCP [尽量阻塞住] ,等我们write完1000字节之后,取消TCP_CORK,这个时候就能够将1000字节一次发出 。

总结:


   TCP_CORK选项与TCP_NODELAY一样,是控制Nagle化的。      

1) 打开TCP_NODELAY选项,则意味着无论数据包是多么的小,都立即发送(不考虑拥塞窗口)。

2) 如果将TCP连接比喻为一个管道,那TCP_CORK选项的作用就像一个塞子。            

    设置TCP_CORK选项,就是用塞子塞住管道,而取消TCP_CORK选项,就是将塞子拔掉。            

    当TCP_CORK选项被设置时, TCP链接不会发送任何的小包,即只有当数据量达到MSS时,才会被发送 。

     一般当数据传输完成时,通常需要取消该选项,以防被塞住,这样才可以让不够MSS大小的包能及时发出去。

例如下面这段代码:

  1:  int  on = 1;

  2:  setsockopt(sockfd, SOL_TCP, TCP_CORK, &on, sizeof(on)); //set TCP_CORK

  3:   write(sockfd, ...);     //e.g., http header

  4:  sendfile(sockfd, ...); //e.g., http body

  5:   on = 0;

  6:  setsockopt(sockfd, SOL_TCP, TCP_CORK, &on, sizeof(on)); //unset TCP_CORK

本文来自:TCP缓冲区管理算法

感谢作者:TCP缓冲区管理算法

查看原文:Nagle算法-

2370 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传