转自:http://www.tuicool.com/articles/YfM7nm
今天开始学习Socket编程,但是上网查询的一些资料之后发现与之相关的知识太多了,所以我从基础看起,慢慢来,首先来看一下Delayed Ack 和 Nagle Algorithm的内容。
1.Delayed Ack
tcp协议规定在接受到数据段时需要向对方发送一个确认,但如果只是单纯的发送一个确认,代价会比较高(20字节的ip首部,20字节的tcp首部),最好能附带响应数据一起发送给对 方.所以tcp在何时发送ack给对方有以下规定:
1) 当有响应数据要发送时, ack会随响数据立即发送给对方 .
2) 如果没有响应数据,ack的发 送将会有一个延迟,以等待看是否有响应数据可以一起发送 ,这称是"Delayed Ack".但这个延迟最多不会超过500ms,一般为200ms.如果在200ms内有数据要发送,那么ack会随数据一起立即发送给对方.注意这里的延迟200ms,不是指的从接受到对方数据到发送ack的最长等待时间差.而是指的内核启动的一个定时器,它每隔200ms就查看下是否有ack要发送.例如:假设定时器在0ms时启动,对方的数据段在
185ms时到达,那么ack最迟会在200ms时发送,而不是385ms时发送.
3) 如果在等待发送ack期间,对方的第二个数据段又到达了,这时要立即发送ack.但是如果对方的三个数据段相继 到达,那么第二个数据段到达时ack立即发送,但第三个数据段到达时是否立即发送,则 取决于上面两条.
2.Nagle Algorithm
当tcp协议用来传输小的数据段时代码是很高的,并且如果传输是在广域网上,那可能就会引起网络拥塞.Nagle算法就是用来解决这个问题.该算法要求一个TCP连接上最多只能有一个 未被确认(未收到Ack确认) 的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组。相反TCP收集这些少量的分组,并在确认到来时以一 个分组的方式发出去.Host Requirements RFC声明TCP必须实现Nagle算法,但必须为应用提供一种方法来关闭该算法在某个连接上执行。
纳格算法是合并(coalescing)一定数量的输出资料后一次送出。特别的是,只要有已送出的 封包 尚未确认,传送者会持续缓冲封包,直到累积一定数量的 资料 才送出。
算法如下如下:
if 有新资料要传送
if 讯窗大小 >= MSS and 可传送的资料 >= MSS
立刻传送完整MSS大小的segment
else
if 管线中有尚未确认的资料
在下一个确认(ACK)封包收到前,将资料排进缓冲区伫列
else
( MSS=最大segment大小)
为什么要同时介绍这两个知识呢?
因为这两个技术同时使用的话会出现问题,下面来看一下问题的出现场景:
A 和B进行数据传输 : A运行Nagle算法,B运行delayed ACK算法
1. A->B 发一个packet(数据包), B不回应,delay ACK
2. A-> 再发一个packet(数据包)
3. B收到第二个packet(数据包),这时候会回应第一个packet(数据包),即第一个ACK
4. 假设这时候A里的数据已经<MSS,则A将停止发送数据,等待第二个packet(数据包)的ACK
此时问题就来了,因为A没有收到第二个packet的ACK确认,同时数据<MSS,由Nagle算法可以得知,这段数据将被被存到缓冲区等待发送,同时这时候B也在等A再发一个packet然后再回应一个ACK,所以这样A和B就发生了死锁了,但是Delayed Ack是有等待机制的,就是会等待500ms,一般是200ms,如果在这200ms内有数据数据要发送(ACK),就回应一个packet(数据包)的ACK,这样就会打破这种死锁的问题。即 只有当200ms(或小于200ms)的延迟过后双方才会继续传输。
当然我们从上面可以看到这种等待机制还是有副作用的,那就是需要等待:一项数据表明:
在以太网上,传输100000字节仅需1ms,但由于delayed ack和nagle的作用却要花费201ms,这显然对程序的效率产生了很大影响.