TCP-IP详解:Nagle算法
在使用一些协议通讯的时候,比如Telnet,会有一个字节字节的发送的情景,每次发送一个字节的有用数据,就会产生41个字节长的分组,20个字节的IP Header 和 20个字节的TCP Header,这就导致了1个字节的有用信息要浪费掉40个字节的头部信息,这是一笔巨大的字节开销,而且这种Small packet在广域网上会增加拥塞的出现。
如果解决这种问题? Nagle就提出了一种通过减少需要通过网络发送包的数量来提高TCP/IP传输的效率,这就是Nagle算法
Nagle算法
Nagle算法主要是避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。相反,TCP收集这些少量的小分组,并在确认到来时以一个分组的方式发出去。
- if there is new data to send
- if the window size >= MSS and available data is >= MSS
- send complete MSS segment now
- else
- if there is unconfirmed data still in the pipe
- enqueue data in the buffer until an acknowledge is received
- else
- send data immediately
- end if
- end if
- 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算法。
禁用方法:
- 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算法的更多相关文章
- TCP/IP详解 (转)
TCP/IP详解学习笔记(1)-基本概念 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中 ...
- TCP IP详解(转)
大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 网络七层协议简称OSI.TCP/IP刨除了物理层,并把上三层(会话层.表示层和应用层)统称 ...
- 《TCP/IP详解卷1:协议》第19章 TCP的交互数据流-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- TCP/IP详解学习笔记 这位仁兄写得太好了
TCP/IP详解学习笔记(1)-基本概念 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣 ...
- TCP/IP详解学习笔记 这位仁兄写得太好了.(转载)
TCP/IP详解学习笔记 这位仁兄写得太好了 TCP/IP详解学习笔记 这位仁兄写得太好了. http://blog.csdn.net/goodboy1881/category/20444 ...
- 【转】TCP/IP详解学习笔记(二)
TCP/IP详解学习笔记(5)-IP选路,动态选路,和一些细节 1.静态IP选路 1.1.一个简单的路由表 选路是IP层最重要的一个功能之一.前面的部分已经简单的讲过路由器是通过何种规则来根据IP数据 ...
- 《TCP/IP详解:卷一》-TCP部分讲解
TCP/IP协议 作者:Danbo 2015-7-2 本文为参考TCP/IP详解卷一,某些知识点加上了作者自己的理解,如有错误,欢迎指正,可以微博联系我! TCP包格式和IP包格式如下: TCP的正常 ...
- 《TCP/IP详解卷1:协议》第3章 IP:网际协议(1)-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 《TCP/IP详解卷1:协议》第6章 ICMP:Internet控制报文协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
随机推荐
- 作为从业人员,如果一定要学一门新的编程语言,那么它一定是c++
作为从业人员,如果一定要学一门新的编程语言,那么它一定是c++. 无论各种编程语言排行榜如何变化,什么语言最赚钱,想成为真正的程序员,那么c/c++是必修课,因为几乎所有的底层都是c/c++编写的,各 ...
- C++设计模式 之 “对象性能” 模式:Singleton、Flyweight
“对象性能”模式 面向对象很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价.对于通常情况来讲,面向对象的成本大都可以忽略不计.但是某些情况,面向对象所带来的成本必须谨慎处理. 典型模式 # ...
- 01: MySql简介
MySQL其他篇 目录: 参考网站 1.1 数据库介绍 1.2 视图 1.3 触发器 1.4 事物 1.1 数据库介绍返回顶部 1.什么是数据库? 1. 数据库(Database)是按照数据结构来组织 ...
- CRC32是什么?
CRC32:CRC本身是“冗余校验码”的意思,CRC32则表示会产生一个32bit(8位十六进制数)的校验值.由于CRC32产生校验值时源数据块的每一个bit(位)都参与了计算,所以数据块中即使只有一 ...
- [c/c++]指针(4)
现在讲一下指针的主要用途和常见错误. [用途] 1.用作形参 首先,常见新手写交换函数: void swap(int a,int b){ int t = a; a = b; b = t; } 主函数里 ...
- linux下安装evernote国际版
一.背景 由于之前一直将笔记记录在evernote,因此现在转到linux下需要使用工具来记录笔记到evernote上 OS : Ubuntu 16.04 (xenial) 二.linux版everp ...
- HDU 4638Group (莫队)
Group Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)题解
题意:5*6的格子,你翻一个地方,那么这个地方和上下左右的格子都会翻面,要求把所有为1的格子翻成0,输出一个5*6的矩阵,把要翻的赋值1,不翻的0,每个格子只翻1次 思路:poj 1222 高斯消元详 ...
- flink架构介绍
前言 flink作为基于流的大数据计算引擎,可以说在大数据领域的红人,下面对flink-1.7的架构进行逻辑上的分析并和spark做了一些关键点的对比. 架构 如图1,flink架构分为3个部分,cl ...
- 项目梳理4——WebApi项目,使用注释填充Description字段
web.config中添加连接字符串: 为webapi添加Description,使用注释来填充此字段 对于所有引用的xxxx.base项目设置生成的xml文档,注意release.debug下都需设 ...