河源北京网站建设,wordpress推送到百度,成全视频在线直播观看,福州自助建站网站一、流量控制
一般来说#xff0c;我们总是希望数据传输得更快一些#xff0c;但是如果发送方把数据发送得太快#xff0c;接收方可能来不及接收#xff0c;造成数据的丢失#xff0c;数据重发#xff0c;造成网络资源的浪费甚至网络拥塞。所谓的流量控制#xff08;fl…一、流量控制
一般来说我们总是希望数据传输得更快一些但是如果发送方把数据发送得太快接收方可能来不及接收造成数据的丢失数据重发造成网络资源的浪费甚至网络拥塞。所谓的流量控制flow control就是让发送方的发送速率不要太快要让接收方来得及接收。利用滑动窗口机制就可以很方便的在TCP连接上实现流量控制。
用滑动窗口机制使用关闭窗口控制发送方发送数据。发送方持续发送报文但是接收方处理不过来那就是浪费网络资源。 使⽤ Nagle 算法用于自动连接许多的小缓冲消息尽可能发送大块数据避免网络中充斥着许多小数据块浪费网络资源。 二、拥塞控制
网络是一个相当复杂的环境我们发送数据不能只考虑交互两端的情况基于交互两端的情况做出流量控制是不够的我们还需要考虑网络的情况网络上的包就像来来往往的车流如果没有管制那将是灾难的试想如果在十字路口没有红绿灯还没有交警那将会发生什么
1. 拥塞的形成 如上图当数据到达一个大的管道如一个快速局域网并向一个较小的管道如一个较慢的广域网发送时便会发生拥塞。当多个输入流到达一个路由器而路由器的输出流小于这些输入流的总和时也会发生拥塞。
上图显示了一个典型的大管道向小管道发送报文的情况。之所以说它典型是因为大
多数的主机都连接在局域网上并通过一个路由器与速率相对较低的广域网相连我们再次
假定图中上半部分的报文段9 ~ 20都是相同的而图中下半部分的 ACK也都是相同的。 在该图中我们已经标记路由器 R1为“瓶颈”因为它是拥塞发生的地方。假定瓶颈路由器具有足够的容纳这 20个分组的缓存。那么将正常进行否则就会引起路由器丢弃分组。 而在TCP的实现上数据包发送出去我们通过一个计时器timer采样了RTT并计算RTO如果因为网络拥堵网络包应答超时或丢失那么发送方将重发而本身网络就处理能力有限而且拥堵这时候还重发试想如果成千上万的网络包都这样这无疑雪上加霜形成“网络风暴”最后网络瘫痪。
2.拥塞窗口
前面我们说过如果我们采用一问一答的方式即我发送一个包你应答一次然后我再发送下一个包这传输速率显然很慢严重影响我们的用户体验所以我们制定了一个策略窗口控制滑动窗口即相应数量以内的包在未被确认的情况下发送方也能继续发送这提高了数据的传输速度。
下图为滑动窗口的初步商定 但是我们只考虑发送方和接收方的情况下而进行窗口大小的设定如果窗口过大发送方一股脑的将数据快速传输出去而网络的传输能力又有限就会导致包的传输超时或者丢包。 所以我们需要在上面窗口大小的基础上加上“网络传输能力”的限制这个窗口的大小就是拥塞窗口。对拥塞窗口大小的调整就是拥塞控制。 注意前面我们说过发送窗口的大小受到接收方窗口大小和拥塞窗口大小的限制。
发送窗⼝的值是swnd min(cwnd, rwnd)也就是拥塞窗⼝和接收窗⼝中的最⼩值。
拥塞窗⼝ cwnd是发送⽅维护的⼀个的状态变量它会根据⽹络的拥塞程度动态变化的。 3. 什么影响拥塞窗口的大小 1网络没有拥塞拥塞窗口就会变大 2网络有拥塞拥塞窗口就会变小
另外“网络是否拥塞”是通过是否发生了超时重传超时重传就认为网络拥塞。 4. 了解TCP拥塞控制的前提 1假设接收方的总是有足够大的缓冲区发送方的发送窗口仅由网络的拥塞程度决定不考虑接收方的接收窗口大小事实上发送窗口的大小由拥塞窗口和接收方的接收窗口大小共同控制 2以最大报文段MSS的个数作为讨论单位而不是以字节为单位
发送窗口、拥塞窗口、接收窗口实际都是以字节为单位但是为了更好的探讨使用报文段MSS为单位。 3发送方以n个包的发送为一轮在这n个包的发送过程内不用考虑接收方是否应答
5. 拥塞控制主要是四个方法算法 1慢启动 2拥塞避免 3拥塞发生 4快速恢复。 三次握手后通过报文中的MSS选项得知通信双方最大报文的大小、窗口大小即滑动窗口大小。 TCP模块通常将MSS设置为MTU-40字节减掉的这40字节包括20字节的TCP头部和20字节的IP头部。这样携带TCP报文段的IP数据报的长度就不会超过MTU假设TCP头部和IP头部都不包含选项字段并且这也是一般情况从而避免本机发生IP分片。对以太网而言MSS值是14601500-40字节。
窗口大小随着数据发送不断变化发送端开始发送数据。 1慢启动 前面我们讲到发送端为了提高网络效率不会发送一个确认一个而是在一定范围内的报文发送不需要应答也能继续发送数据。于是有了滑动窗口。 同理我们也不能上来就一股脑的发送报文数据这会导致接收端处理不过来丢包网络传输不过来产生拥塞。 所以我们需要慢慢来一步步的提高传输窗口试探网络的承受能力达到一个合理的值。 慢启动的规则
当发送⽅每收到⼀个 ACK拥塞窗⼝ cwnd 的⼤⼩就会加 1个MSS单位大小的字节数。慢启动的拥塞窗口增加也不是没有上限的有时我们会达到中间路由器的极限此时分组将被丢弃。所以需要一个门限ssthresh初始值为65535个字节。拥塞窗口初始化大小为1个MSS单位大小的字节数。当慢启动阶段的拥塞窗口大小增长到门限ssthresh的时候慢启动阶段结束进入拥塞避免阶段。 可以看出慢启动算法发包的个数是指数性的增⻓。
每个报文的应答确认ACK都会让拥塞窗口增加一个MSS单位的大小如上图第一个往返时间内的ACK让cwnd增加一个MSS的字节数第二个往返时间段内发送2个返回两个ACK让窗口变成4个MSS大小的字节数一次类推直到cwnd ssthresh,停止慢启动变为拥塞避免即这个时候就要注意增长不要让网络拥塞了需要更小心的试探网络让增长的幅度减小。 2拥塞避免 慢启动阶段停止进入拥塞避免阶段这个阶段就是更加小心的慢慢试探网络情况所以增长的幅度降低。
拥塞避免规则
变成了每次ACK增长1/cwnd个单位的MSScwnd为本次往返时间内的拥塞窗口大小MSS为最大报文段大小。那么本次往返时间段内共增加了1个MSS单位大小的字节数。拥塞避免阶段也不可能无休止的增长上去当触发了重传机制也就进⼊了「拥塞发⽣算法」。 3拥塞发生 当⽹络出现拥塞也就会发⽣数据包重传重传机制主要有两种
超时重传快速重传
超时重传拥塞发生时的算法规则
网络是复杂的发生超时重传发送方压根不知道网络发生了什么只能往最坏的情况去想我们假设网络拥堵严重此时就只能让拥塞窗口即cwnd 1MSS字节重新试探网络。既然是重新试探网络则重新启动慢启动阶段。但是由于第一次的教训为了避免给网络添堵sshthresh cwnd /2cwnd为发生超时重传时的拥塞窗口大小。
简要概括就是
cwnd 1MSS字节可谓是一夜回到解放前。sshthresh cwnd /2cwnd为发生超时重传时的拥塞窗口大小。进入慢启动阶段。 快速重传拥塞发生时的算法规则
上面那种发生超时重传网络流量断崖式下跌这是武断的所以人们在已有的基础上进行了改进在收到3个重复的 ACK时就开启重传而不用等到RTO超时导致流量断崖式下跌。因为TCP认为你都收到ACK了说明网络也没有那么差。 快速重传有两种实现方式TCP Tahoe、TCP Reno。
TCP Tahoe的实现和RTO超时一样。TCP Reno的实现是
cwnd cwnd /2sshthresh cwnd进入快速恢复算法——Fast Recovery 4快速恢复算法 Fast Recovery 快速重传和快速恢复算法一般同时使用。快速恢复算法是认为你还有3个Duplicated Acks说明网络也不那么糟糕所以没有必要像RTO超时那么强烈。 注意正如前面所说进入Fast Recovery之前cwnd 和 sshthresh已被更新
cwnd cwnd /2sshthresh cwnd 快速恢复的算法规则如下
TCP Reno版本
cwnd sshthresh 3 * MSS 3的意思是确认有3个数据包被收到了重传3个重复ACK指定的数据包如果再收到3个重复的ACK一样的ACK那么认为重传成功此时cwnd cwnd 1MSS单位字节如果收到了新的ACK那么cwnd sshthresh 然后就进入了拥塞避免的算法了。 TCP New Reno版本
上面这个算法也有问题那就是——它依赖于3个重复的ACK。注意3个重复的ACK并不代表只丢了一个数据包很有可能是丢了好多包。但这个算法只会重传一个而剩下的那些包只能等到RTO超时重传于是进入了恶梦模式——超时一个窗口就减半一下多个超时会超成TCP的传输速度呈级数下降而且也不会触发Fast Recovery算法了。 通常来说正如我们前面所说的SACK或D-SACK的方法可以让Fast Recovery或Sender在做决定时更聪明一些但是并不是所有的TCP的实现都支持SACKSACK需要两端都支持所以需要一个没有SACK的解决方案。而通过SACK进行拥塞控制的算法是FACK。 于是1995年TCP New Reno参见 RFC 6582 算法提出来主要就是在没有SACK的支持下改进Fast Recovery算法。
当sender这边收到了3个Duplicated Acks进入Fast Retransimit模式开发重传重复Acks指示的那个包。如果只有这一个包丢了那么重传这个包后回来的Ack会把整个已经被sender传输出去的数据ack回来。如果没有的话说明有多个包丢了。我们叫这个ACK为Partial ACK。一旦Sender这边发现了Partial ACK出现那么sender就可以推理出来有多个包被丢了于是乎继续重传sliding window里未被ack的第一个包。直到再也收不到了Partial Ack才真正结束Fast Recovery这个过程。
我们可以看到这个“Fast Recovery的变更”是一个非常激进的玩法他同时延长了Fast Retransmit和Fast Recovery的过程。 5其他算法 TCP Vegas 拥塞控制算法
这个算法1994年被提出它主要对TCP Reno 做了些修改。这个算法通过对RTT的非常重的监控来计算一个基准RTT。然后通过这个基准RTT来估计当前的网络实际带宽如果实际带宽比我们的期望的带宽要小或是要多的活那么就开始线性地减少或增加cwnd的大小。如果这个计算出来的RTT大于了Timeout后那么不等ack超时就直接重传。Vegas 的核心思想是用RTT的值来影响拥塞窗口而不是通过丢包 这个算法的论文是《TCP Vegas: End to End Congestion Avoidance on a Global Internet》这篇论文给了Vegas和 New Reno的对比 关于这个算法实现你可以参看Linux源码/net/ipv4/tcp_vegas.h /net/ipv4/tcp_vegas.c HSTCP(High Speed TCP) 算法
这个算法来自RFC 3649Wikipedia词条。其对最基础的算法进行了更改他使得Congestion Window涨得快减得慢。其中
拥塞避免时的窗口增长方式 cwnd cwnd α(cwnd) / cwnd丢包后窗口下降方式cwnd (1- β(cwnd))*cwnd
注α(cwnd)和β(cwnd)都是函数如果你要让他们和标准的TCP一样那么让α(cwnd)1β(cwnd)0.5就可以了。 对于α(cwnd)和β(cwnd)的值是个动态的变换的东西。 关于这个算法的实现你可以参看Linux源码/net/ipv4/tcp_highspeed.c TCP BIC 算法
2004年产内出BIC算法。现在你还可以查得到相关的新闻《Google美科学家研发BIC-TCP协议 速度是DSL六千倍》 BIC全称Binary Increase Congestion control在Linux 2.6.8中是默认拥塞控制算法。BIC的发明者发这么多的拥塞控制算法都在努力找一个合适的cwnd Congestion Window而且BIC-TCP的提出者们看穿了事情的本质其实这就是一个搜索的过程所以BIC这个算法主要用的是Binary Search——二分查找来干这个事。 关于这个算法实现你可以参看Linux源码/net/ipv4/tcp_bic.c TCP WestWood算法
westwood采用和Reno相同的慢启动算法、拥塞避免算法。westwood的主要改进方面在发送端做带宽估计当探测到丢包时根据带宽值来设置拥塞窗口、慢启动阈值。 那么这个算法是怎么测量带宽的每个RTT时间会测量一次带宽测量带宽的公式很简单就是这段RTT内成功被ack了多少字节。因为这个带宽和用RTT计算RTO一样也是需要从每个样本来平滑到一个值的——也是用一个加权移平均的公式。 另外我们知道如果一个网络的带宽是每秒可以发送X个字节而RTT是一个数据发出去后确认需要的时候所以X * RTT应该是我们缓冲区大小。所以在这个算法中ssthresh的值就是est_BD * min-RTT(最小的RTT值)如果丢包是Duplicated ACKs引起的那么如果cwnd ssthresh则 cwin ssthresh。如果是RTO引起的cwnd 1进入慢启动。 关于这个算法实现你可以参看Linux源码 /net/ipv4/tcp_westwood.c 拥塞算法示意图
以上就是拥塞控制的全部内容了看完后你再来看下⾯这张图⽚每个过程我相信你都能明⽩ 拥塞避免是发送方使用的流量控制而通告窗口则是接收方进行的流量控制。前者是发送方感受到的网络拥塞的估计而后者则与接收方在该连接上的可用缓存大小有关。