TCP在发送端和接收端有两个窗口,发送端的是拥塞窗口而接收端的就叫做接收窗口,两个窗口的作用不同 ,所谓的流量控制就是收发端的速率要匹配,决定权在接收端而不在发送端,因为发送的慢了可以提速,而 接收不了就意味着丢包,这就好比冷了可以穿衣而热了只有扒皮一样。因此对于收发端,流量控制主要由接 收端控制,因此接收窗口就表示“我能接收多少”,按照这个数字发送,在该连接独占网络并且带宽无限的 情况下流量是平滑的。接收端的接收窗口将按照自己的能力向前滑动。 然而网络环境不是那么理想的,第一任何连接不能独占带宽,第二,带宽也不是无限,因此即使接收 端建议发送端发送多少数据,发送端也有确保公平的义务,因此发送端也有一个窗口,叫做拥塞窗口,指当 前的网络状况只能发送这么多数据报,一般发送端可以发送的数据是接收窗口和拥塞窗口的最小值,由于 tcp是全双工的协议,连接两端都是接收者和发送者,因此每端都有两个窗口,其中的拥塞窗口和实际的发 送窗口自己维护,而接收窗口要在tcp协议头中传给对方,让对方根据这个窗口和自己的拥塞窗口抉择自己 的实际发送窗口。
1.慢启动并不慢
慢启动是一种拥塞控制机制,只影响拥塞窗口,注意,实际的发送窗口需要取拥塞窗口和对端传来的接收窗 口的最小值,慢启动的过程中,拥塞窗口不断增加,因为tcp连接刚启动,并不知道网络的实际情况,需要 用一种试探的方式慢慢平滑增加发送窗口的大小,增加的过程是十分快的,是指数增长的,直到发生拥塞或 者达到事前配置好的一个阀值,如是是拥塞发生了,那么肯定要调整拥塞窗口了,事实上由于慢启动实际很 快,如果仅仅有慢启动,那么网络很快就拥堵不堪了。
2.拥塞发现
每一个数据报都有一个定时器,如果定时器超时还没有ack回来,那么就说明该数据没有到达目的地,十有 八九是网络拥塞了,tcp的设计者必须假定网络率很低,此时tcp发送端将采取措施,最重要的就是 重新开始慢启动,并且将慢启动阀值减小,当拥塞窗口到达该阀值的时候(由于阀值减小了,肯定比刚开始 的慢启动过程先到这种状态),实行另一种拥塞控制方法--拥塞避免,就是拥塞避免,其实就是将慢启动的 指数增加窗口大小改为线性增加,从而渐渐将拥塞窗口调整到一个合适的大小。
3.快速重传
还有一种情况会直接使用拥塞避免,那就是当发送端收到三个重复的ack的时候,说明接收端收到了三个序 列号靠后数据报,但都不是接收窗口最前面的那个,因此说明那个数据十有八九是丢了,因此可以预测拥塞 发生了,因此将拥塞窗口减半,然后线性增加,这就是加增乘减原则。顺便,tcp接收数据的顺序只要在窗 口内并不一定非要按序,只要OS的协议栈实现支持缓存窗口内的断序数据即可。
4.加增乘减原则
该原则体现了公平,因为拥塞窗口增加只会优惠到自己,而减小却会优惠很多别的连接,每一个连接都有维 护公平的义务,本着优惠均等的原则,自己的行为应该让包括自己在内的所有连接得到均等的实惠,因此优 惠只有一个自己的时候用加法,而优惠很多大家的时候用乘法。
5.快速恢复算法
快速重传虽然通过减半拥塞窗口的办法可以减缓拥塞,但是自己过分的让步可能会引起别人贪婪地掠夺,虽 然我让步了,减半了拥塞窗口,但是我是靠接收了三个重复ack才得到这个消息的,而不是一个包的超时, 如果在第一个重复ack时我就开始快速重传,那么此时我的拥塞窗口已经加了三个了,因此需要补偿我无辜 的等待三个ack,因此快速恢复过程是对快速重传的修正,将拥塞窗口减半后加上了3
6.拥塞窗口何时稳定
如果仅仅考虑拥塞控制,那么貌似拥塞窗口会一直这么指数增-乘减-加增-乘减-指数增-...循环下去,是的 ,确实是这样,但是通过统计tcp连接的速率和流量,发现并不是这样,而是发送端的窗口总是会稳定于一 个特定的值,而该值就是接受方的接收窗口的大小,最终,一切都被定格在了接收方的协议栈处理性能以及 缓冲区内存情况了,拥塞窗口只要增加到接收方的接收窗口就不再增加和减少了,除非接收窗口增加或者减 小以及拥塞发生了,总之,拥塞窗口和接收窗口的最小值决定发送窗口,如果拥塞窗口增加到了接收窗口的 大小就不再继续慢启动或者拥塞避免。
7.网络设备和端机的能力
tcp的流量控制在端机,而拥塞却取决于中间的路由器等网络设备以及网线,它们处理能力的匹配至关重要 ,虽然端机远远不敌中间设备,可是中间设备却由多数端机分享,试想如果端机的性能超越了网络设备,那 么流量控制窗口将会很大,如此拥塞窗口将在增加到流控窗口之前出现拥塞,如此一来将会导致频繁调整发 送窗口,流控窗口也就失去了意义,虽然接收端能收那么多数据,可是发送端却怎么也到不了该制高点,虽 然到不了但是还是会不懈的慢启动-拥塞停等-快速重传-...俨然网络上的西西弗斯神话。
8.tcp是全双工不停等的
如果按照很多教科书上所讲的方式理解tcp,那么tcp就是一个半双工的协议,一方在发送了数据之后必须等 待确认才能继续发送,就是一问一答式,可是看一下tcp的协议头,包含一个ack字段和seq字段,这就说明 tcp可以在发送数据的时候将ack一同捎带过来,正是如此它才是全双工的。另外它也不是一个单纯的停等协 议,而是基于窗口机制的批量发送/确认协议。
9.一个比喻
开车的人或者看过司机开车都知道,汽车的性能和道路的路况(拥塞程度和限速等)以及司机的技术水平共同 决定车能开多快,如果情况一,路况不好(拥塞控制),那么再好的车再好的司机都会不停的做刹车,踩油门 ,换档等动作,所有车都一样,看起来不够稳定,如果情况二,路况好,司机也好,但车不好(流量控制), 虽然很稳定,但白瞎了这条路和司机了,如果情况三,路好,车好,司机不够娴熟(流量控制),司机的动作 和第一种情况一样,但是好的司机却不这样。情况一指的是网络设备不好,情况二指的是端机不好,情况三 可能是下面的情况,端机好,可是端机上的诸如内存管理算法之类的软性能很糟糕。