TCP的Nagle算法和糊涂窗口综合症

现象:

今天下午大雄说在测试过程中发现个奇怪的现象,A,B程序在同一台机器上,A做为server,B做为client。

A给B不停地发数据,数据量比较大,可能100M的数量级。发了一段时间后,发现A的程序日志是write成功了,

但B并没有收到或者很慢才收到。第一反应是捉包,用tcpdump嘛!大雄早就捉好包了,只是看起来很奇怪,

现象是前面30来个包很正常,忽然有个包B回ACK慢了一点点,A接下来等了200MS才发下个包了。然后变态

的事情发生了,接下去A所有的包都是发一个小包,再等200MS再发一个大包。

image

19901是A的端口,47347是B的端口,第一个红色框就是第一次出现ACK回得慢的地方。后面发生一次窗口为0,

这个下面的包再一起说,由于这里说的原因,这个win是不对的,因为包里没有SYN包,所以不知道放大倍数

(根据猜应该是128倍)所以再捉了一次包,这次现象就更清楚了些:

image

注:这次A是19901,B是9705

这里跟上次的现象一样,只是出现了杯具的【TCP Previous segment lost】根据之前的经验,这个应该是tcpdump

捉不到数据,丢了比较重要一段,但没关系,下面的情况告诉了我们一些信息,当发包出现意外后,还是A机就塞了

一个15K的包过来,一把将窗口塞满,然后接下去就是重复,A发一个小包,B的ACK回得很快,A等了200MS再发一

个15K的大包塞满窗口,B的ACK照样回得很快。

这里还有个细节要注意,回到SYN包去看,发现MSS竟然有16K大

image

MSS = MTU – (IP头 +TCP头) 由于是同一台机,所以走的是回环,ifconfig看一个lo的MTU是16436所以MSS就为16396(16436-40)

image

问题解决:

后来春哥研究了一下,关闭了Nagle算法,问题不再出现。

setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&value,sizeof(int));

问题分析:

好了,主题来了,什么是Nagle算法?《TCP/IP 详解》的第19章有提起这个,不过由于这本书写得好早,所以只是比较

简单的描述,网上一般将Nagle和糊涂窗口综合症(Silly Window Syndrome)一起讨论,《TCP/IP 详解》的第22章

也有提起,不过这里这里说得更为详细一下和与时俱进一些。详细的原理,大家参与上面两个链接就行了,我这里简单

比喻一下。

       网络就好比一条铁路,带宽就像这条铁路全部排满能停多少车厢假设1000个。MTU就好比一辆火车最多能拉多少车

箱(算上火车头),火车头就好像是IP头+TCP头,车箱就是MSS,这里假设MTU为100节,那MSS就为99,因为要减去火车头。

同时我们规定,从A出发到B的车,一次发多少车箱,要取决于两个条件:

  1. 是A有多少车箱要发(A的缓存)
  2. 是B有多少地方可以停(窗口)要B打电话通知(ACK)

那么带宽使用率最高的情况是,开满10趟车,一车带99个车箱。而利用率最低的情况是一个车头带一个车箱,500趟。

第一种只要10个头就能带990个车箱过去,而第二种要500个头只能带500个。后面这种叫小包,这种情况就叫糊涂窗口综合症。

这种情况有可能是两方面引起的。

  1. 由于发车方装货太慢了。(装好一个发一个)
  2. B站腾出车位太慢。(有一个空位通知一次)

而Nagle算法就是为了减少小包,解决问题1的方法之一,他的思路其实就是停,等。等你装多点车箱我再走。

他要满足以下主要条件:

  1. 窗口>=MSS 或者 发送的数据>=MSS。也主就是对方告诉我B站车位大于99个,或者A站在等着要出去的车大于99个。
  2. 或者等待时间超过200MS --- 这个时间跟我们的例子好像对得上。
  3. 要不路上只能有一个上最多只能有一个未被确认的未完成的小分组,小分组的意思就是小于MSS。也就是说,你想不

带慢99节车箱跑可以,但你在路上最多只有一辆车可以这样,只有B站通知你这个车到了,你才能再发一辆。

还有问题:

这样看,我们似乎是要受到Nagle算法的限制的。因为MSS好大有16K,而我们的包一般最大只有3K左右,也就是说正常

情况下,我们只会是A发一个包,B回一个ACK,A再发一个包。是的,前面一直是这样的。但后面为何为有200MS的出现呢?

按照Nagle算法,你回了ACK,我就可以再发一个包了,也就是不用等200MS的超时。我们的例子可以看出B回ACK还是

很快的,除了出事前的最后一次慢了一点点。所以关闭Nagle算法会不会是这个问题的冶本方案呢?这个200MS是不是

真的Nagle算法引起的呢?从目前的包来看,并不符合Nagle算法的描述,也不符合超时重发,所以这个很奇怪!

各位大侠有什么建议麻烦给我说一下!

个人猜测可能有以下原因:

1.同一台机,Tcpdump捉的数据不一定是准确的。

2.可能跟操作系统,或者进程的缓冲区有关,因为本地发MSS太大,速度太快。

3.有空可以看看linux的源码,tcp_nagle_check函数

2017.06.19 记:

最近看了一些关于TCP的文章,同时也对这个问题进行了一定的思考,后来找了一下资料,发现这里

说的很有可能是这个原因,因为接收端的缓存满了,导致发送方超时重发,同时又引起RTO的退避策略

http://blog.csdn.net/dog250/article/details/51865031

附录:

这两个链接似乎有相同的问题

http://weibo.com/p/1001603821691477346388

http://www.v2ex.com/t/192510

 

转载于:https://my.oschina.net/mawx/blog/336390

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值