超详细的wireshark笔记(3)-TCP窗口和TCP重传

TCP的窗口

假如你是一位勤劳的快递员,要送100个包裹到某公司去,怎样送货才科学?

最简单的方式是每次送1个,总共跑100。当然这也是最慢的方式,因为往返次数越多,消耗的时间就越长。除了需要减肥的快递员,一般人不会选择这种方式。

最快的方式应该是一口气送100,这样只要跑一趟就够了。可惜现实没有这么美好,往往存在各种制约因素:公司狭小的前台只容得下20个包裹,要等签收完了才能接着送;更令人郁闷的是,电瓶车只能装10个包裹。综合这两个因素,不难推出电瓶车的运力是效率瓶颈,而前台的空间则不构成影响。

 

快递送货的策略非常浅显,几乎人人可以理解,而TCP传输大块数据的策略却很少人懂。事实上这两者的原理是相似的。

 

TCP显然不用电瓶车送包,但它也有“往返”的需要。因为发包之后并不知道对方能否收到,要一直等到确认包到达,这样就花费了一个往返时间。假如每发一个包就停下来等确认,一个往返时间里就只能传一个包,这样的传输效率太低了。最快的方式应该是一口气把所有包发出去,然后一起确认。但现实中也存在一些限制:接收方的缓存(接收窗口)可能一下子接受不了这么多数据;网络的带宽也不一定足够大,一口气发太多会导致丢包事故。

所以,发送方要知道接收方的接收窗口和网络这两个限制因素中哪一个更严格,然后在其限制范围内尽可能多发包。这个一口气能发送的数据量就是传说中的TCP发送窗口

 

发送窗口对性能的影响有多大?

一图胜千言,下图显示了发送窗口为1个MSS(即每个TCP包所能携带的最大数据量)和2个MSS时的差别。在相同的往返时间里,右边比左边多发了两倍的数据量。而在真实环境中,发送窗口常常可以达到数十个MSS

 

 

假如接收方处理数据的速度跟不上接收数据的速度,缓存就会被占满,从而导致接收窗口为0

 

发送窗口和MSS有什么关系?

发送窗口决定了一口气能发多少字节,而MSS决定了这些字节要分多少个包发完

举个例子,在发送窗口为16000字节的情况下,如果MSS1000字节,那就需要发送16000/1000=16个包;而如果MSS等于8000,那要发送的包数就是16000/8000=2

 

发送方在一个窗口里发出n个包,是不是就能收到n个确认包?

不一定,确认包一般会少一些。由于TCP可以累积起来确认,所以当收到多个包的时候,只需要确认最后一个就可以了。

 

经常听说“TCP Window Scale”这个概念,它究竟和接收窗口有何关系?

在TCP刚被发明的时候,全世界的网络带宽都很小,所以最大接收窗口被定义成65535字节。随着硬件的革命性进步,65535字节已经成为性能瓶颈了,怎么样才能扩展呢?TCP头中只给接收窗口值留了16 bit,肯定是无法突破65535的。

1992年的RFC 1323中提出了一个解决方案,就是在三次握手时,把自己的Window Scale信息告知对方。由于Window Scale放在TCP头之外的Options中,所以不需要修改TCP头的设计。Window Scale的作用是向对方声明一个Shift count,我们把它作为2的指数,再乘以TCP头中定义的接收窗口,就得到真正的TCP接收窗口。

 

下面的属性表示的是接收的窗口,接收的窗口=Window X Winsow size scaling factor,也就是304X128=38912,wireshark已经帮助我们计算好了

 

TCP重传

发送方的发送窗口是受接收方的接收窗口和网络影响的,其中限制得更严的因素就起决定作用。接收窗口的影响方式非常简单,只要在包里用"Win="告知发送方就可以了。而网络的影响方式非常复杂。

网络之所以能限制发送窗口,是因为它一口气收到太多数据时就会拥塞。拥塞的结果是丢包,这是发送方最忌惮的。能导致网络拥塞的数据量称为拥塞点,发送方当然希望把发送窗口控制在拥塞点以下,这样就能避免拥塞了。但问题是连网络设备都不知道自己的拥塞点,即便知道了也无法通知发送方。这种情况下发送方如何避免触碰拥塞点呢?

 

逐次增加发送量,直到网络发生拥塞,这样得到的最大发送量能定为该连接的拥塞点吗?

这是一个好办法,但没这么简单。网络就像马路一样,有的时候很堵,其他时候却很空(北京的马路除外)。所以拥塞点是一个随时改变的动态值,当前试探出的拥塞点不能代表未来。

难道就没有一个完美的方案吗?很遗憾,还真的没有。自网络诞生数十年以来,涌现过无数绝顶聪明的工程师,就是没有一个人能解决这个问题。幸好经过几代人的努力,总算有了一个最靠谱的策略。这个策略就是在发送方维护一个虚拟的拥塞窗口,并利用各种算法使它尽可能接近真实的拥塞点。网络对发送窗口的限制,就是通过拥塞窗口实现的。下面我们就来看看拥塞窗口如何维护。

 

1.连接刚刚建立的时候,发送方对网络状况一无所知。如果一口气发太多数据就可能遭遇拥塞,所以发送方把拥塞窗口的初始值定得很小。RFC的建议是23或者4MSS,具体视MSS的大小而定。

 

2.如果发出去的包都得到确认,表明还没有达到拥塞点,可以增大拥塞窗口。由于这个阶段发生拥塞的概率很低,所以增速应该快一些。RFC建议的算法是每收到n个确认,可以把拥塞窗口增加nMSs。比如发了2个包之后收到2个确认,拥塞窗口就增大到2+2=4,接下来是4+4=8,8+8=16…这个过程的增速很快,但是由于基数低,传输速度还是比较慢的,所以被称为慢启动过程

 

3.慢启动过程持续一段时间后,拥塞窗口达到一个较大的值。这时候传输速度比较快,触碰拥塞点的概率也大了,所以不能继续采用翻倍的慢启动算法,而是要缓慢一点。RFC建议的算法是在每个往返时间增加1个MSS。比如发了16个MSS之后全部被确认了,拥塞窗口就增加到16+1=17个Mss,再接下去是17+1=18

18+1=19 这个过程称为拥塞避免。从慢启动过渡到拥塞避免的临界窗口值很有讲究。如果之前发生过拥塞,就把该拥塞点作为参考依据。如果从来没有拥塞过就可以取相对较大的值,比如和最大接收窗口相等。全过程可以用图表示。

 

无论是慢启动还是拥塞避免阶段,拥塞窗口都在逐渐增大,理论上一定时间之后总会碰到拥塞点的。那为什么我们平时感觉不到拥塞呢?原因有很多,如下所示。

  • 操作系统中对接收窗口的最大设定多年没有改动,比如Windows在不启用"TCP window scale option"的情况下,最大接收窗口只有64KB。而近年来网络有了长足进步,很多环境的拥塞点远在64KB以上。也就是说发送窗口已经被限制在64KB了,永远触碰不到拥塞点
  • 很多应用场景是交互式的小数据,比如网络聊天,所以也不会有拥塞的可能。
  • 在传输数据的时候如果采用同步方式,可能需要的窗口非常小。比如采用了同步方式的NFS写操作,每发一个写请求就停下来等回复,而一个写请求可能只有4KB
  • 即便偶尔发生拥塞,持续时间也不足以长到能感受出来,除非抓了网络包进行数据分析、对比。

 

拥塞之后会发生什么情况呢?对发送方来说,就是发出去的包不像往常一样得到确认了。不过收不到确认也可能是网络延迟所致,所以发送方决定等待一小段时间后再判断。假如迟迟收不到,就认定包已经丢失,只能重传了。这个过程称为超时重传。如图所示,从发出原始包到重传段时间称为RTO

 

下图显示了发生超时重传时拥塞窗口的变化。

不难想象,超时重传对传输性能有严重影响。原因之一是在RTO阶段不能传数据,相当于浪费了一段时间;原因之二是拥塞窗口的急剧减小,相当于接下来传得慢多了。以我的个人经验,即便是万分之一的超时重传对性能的影响也非同小可。我们在Wireshark中如何检查重传情况呢?单击分析->专家信息。在Note中的retransmission就是了。

 

之后就可以根据Sequence过滤出原始包和重传包了

 

有时候拥塞很轻微,只有少量的包丢失。还有些偶然因素,比如校验码不对的时候,会导致单个丢包。这两种丢包症状和严重拥塞时不一样,因为后续有包能正常到达。当后续的包到达接收方时,接收方会发现其Seq号比期望的大,所以它每收到一个包就Ack一次期望的Seq号,以此提醒发送方重传。当发送方收到3个或以上重复确认DupAck)时,就意识到相应的包已经丢了,从而立即重传它。这个过程称为快速重传。之所以称为快速,是因为它不像超时重传一样需要等待一段时间。

 

 

下面是一些总结的结论

  • 没有拥塞时,发送窗口越大,性能越好。所以在带宽没有限制的条件下,应该尽量增大接收窗口,比如启用Scale Option(Windows上可参考KB 224829)。
  • 如果经常发生拥塞,那限制发送窗口反而能提高性能,因为即便万分之一的重传对性能的影响都很大。在很多操作系统上可以通过限制接收窗口的方法来减小发送窗口,Windows上同样可以参考KB 224829
  • 超时重传对性能影响最大,因为它有一段时间(RTO)没有传输任何数据,而且拥塞窗口会被设成1个MSS,所以要尽量避免超时重传
  • 快速重传对性能影响小一些,因为它没有等待时间,而且拥塞窗口减小的幅度没那么大。
  • SACK和NewReno有利于提高重传效率,提高传输性能。
  • 丢包对极小文件的影响比大文件严重。因为读写一个小文件需要的包数很少,所以丢包时往往凑不满3个Dup Ack,只能等待超时重传了。而大文件有较大可能触发快速重传。

文章整理自《wireshark网络分析就这么简单》

 

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值