上一章说到TCP的缓存机制,这一回接着往下讲

流量控制

首先,要明确流量控制是针对谁而言的.之前说过发送方会维护有一个发送窗口(rwnd, receiver window),落在这个发送窗口的数据都可以发送出去,但是可能存在一种情况:发送方发送数据的速度太快,接收方应用层的应用处理数据太慢,导致接收方接收缓存的空间已经满了,那么如果这个时候发送方还可以不断的向发送方发送数据,那么这些数据将没有地方安放.流量控制的目的就是为了控制发送方发送数据的速度.

从上面滑动窗口的执行表现可以看出,只要控制滑动窗口的大小那么就可以控制发送方发送数据的速度.原因很明显,滑动窗口越小,那么发送方可以发送的数据大小越小.在实际的通信过程中,接收方会告诉发送方自己的接收窗口大小,(这点在TCP报文首部中有所体现,之后会再次看到)发送方根据接收方传来的窗口值来设定自己的发送阈值.

这里假设一个情况,当接收方B告诉发送方A自己的接收窗口已经变成0,那么A收到这个消息之后就不再发送数据给B直到接收方B重新发送一个窗口值给A.那么假设B在重新发送窗口值的过程中该报文丢失在网络中,那么造成A收不到该报文,B以为自己报文已经发送给A了.这种情况下就会造成死锁的局面.为了打破这种死锁的现象,TCP设计了一个持续计时器的东西,只要任意一方收到对方发来的窗口大小为0通知,那么马上启动这个持续计时器,当持续计时器时间到期还没收到对方的报文,那么就会发送一个称之为探测报文的数据来探测对方是否真的不能接受数据了.

拥塞控制

在对拥塞控制进行讨论之前,我们需要明白为什么要有拥塞控制以及拥塞控制和流量控制的区别.这两个问题可以放在一起分析

流量控制是为了避免发送方发送数据过快导致接收方来不及处理数据,在讨论流量控制的时候我们忽略了一个前提:网络环境.通信双方不单单要考虑到接收方是否来得及处理这些数据,在发送的时候还要考虑网络环境是否可以承载这么大的数据.如果网络环境出现了拥塞,那么就应该有一定的机制来保证在恶劣的网络环境下还可以进行通信以及不加重网络的拥塞程度.

在讨论拥塞控制的时候,我们应该忽略流量控制,也就是假设通信双方可以及时的处理数据,这样子不会增加拥塞控制的复杂度.

目前拥塞控制有4种算法:

  • 慢开始

  • 拥塞避免

  • 快重传

  • 快恢复

这四种算法并不是单独使用的,而是配合使用.具体算法实现分析如下.

通信双方维护一个叫做拥塞窗口(cwnd, congesion window)的值,这个值取决于网络中的拥塞率,发送方的发送窗口的值就等于拥塞窗口的大小(注意,如上面所说的这里忽略了流量控制,实际中还需要考虑到流量控制),只要网络中没有出现拥塞,那么拥塞窗口的值就可以增大一些,这就意味着发送方可以发送到网络中的数据就越多.只要网络出现拥塞,那么拥塞窗口的值就小一点,减少主机发送数据的大小以避免加剧网络的拥塞率.

上面的方式很好理解,但是问题在于主机如何判断当前网络是否拥塞?到这里我们知道,当网络发生拥塞时,网络中的某一个路由器节点就会丢弃数据.那么当发送方没有收到接收方发来的确认报文就认为网络中可能出现了拥塞.

下面分析一下这四种算法的实现逻辑

慢开始

当主机开始发送数据的时候,cwnd的值是比较小的,这样子就避免了在不知道网络拥塞率的情况下注入大量的数据到网络中.

  • 第一次,发送主机每次只发送小于等于cwnd大小的数据,当收到接收方的确认报文之后,就把cwnd的值翻倍

  • 当第二次发送数据发送方就可以发送小于等于2*cwnd大小,在发送方接收到接收方发来的确认报文之后将cwnd的值再次翻倍.

以此类推.从上面的流程中可以看出慢开始名字的含义体现在其执行表现上是开始起点低,但是其增长速度是指数级的.

拥塞避免

拥塞避免和慢开始很像,只是对于拥塞避免算法而言,其cwnd的增长是以+1的方式,而不是翻倍.也就是说当第4次发送数据的时候,慢开始可以发送最多8cwnd的数据,而拥塞避免只能发送4cwnd的数据.很明显,拥塞避免的cwnd的增长速度为线性的.

为了避免cwnd的增长导致网络拥塞,还需要设置一个慢开始门限的值,作用如下

  • 当cwnd<慢开始门限,使用慢开始算法

  • 当cwnd>慢开始门限,改用拥塞避免算法

  • cwnd = 慢开始门限,两者都可以使用.

在拥塞窗口>慢开始门限之后切换为拥塞避免的原因很简单,慢开始的增长率太快,在接下来很容易就导致网络拥塞,所以改用避免拥塞的方式来避免cwnd增长过快.

当网络出现拥塞的情况下,不管是使用慢开始还是避免拥塞算法,都要执行如下的操作:

  • 把慢开始门限的值降为原来的一半

  • cwnd的值重新置为1个单位,执行慢开始算法.

快重传

在慢开始中我们知道,主机判断在超时时间之内没有收到接受方发送的确认报文就认为出现了拥塞,这个时候开始降低慢开始门限和重置cwnd的值.但是当使用快重传的算法之后,思路就变了.

假设发送方A发送[1,7]序号的报文:P1,P2都已经被接收方B接收并且发出了确认,这个时候B收到P4报文,按照上一篇讲的连续ARQ协议中的说明,这个时候B不能发送对P4的确认,它可以什么都不做,但是按照快重传的算法规定,这个时候B必须再次发送对P2的重复确认.这样子是为了让A知道报文P3没有到达接受方.假设接下来B仍然没有收到P3,而是收到了P5,P6报文,那么B仍然要重新发送P2的确认.这样子接收方A一共收到了4次对P2报文的确认,其中有3次是重复确认.快重传规定当发送方收到对同一个报文的3次重复确认就应该立即重传对方尚未接收到的字段.在这个例子中A应该重新发送报文P3.

快恢复

同样,快重传情况下如果出现了网络拥塞,也需要一个机制来降低主机注入到网络中的数据量,这里就使用快恢复算法.快恢复算法执行表现如下:

  • 当发送方接收到三个重复确认,就把慢开始门限减半,同时把cwnd的值改为慢开始门限的一半.

  • 不执行慢开始算法,而是执行避免拥塞算法.

比较两组对于网络拥塞的处理可以发现快重传更多是为了避免拥塞,回顾快重传中的逻辑其实可以看出当时网络并不一定发生了拥塞,因为如果网络拥塞就不会有好几个报文会到达接收方.所以,快恢复中只是把cwnd降为慢开始门限的一半来防止过大的cwnd可能导致未来拥塞.

接下来,我们考虑接收方接收缓存的限制,即同时考虑拥塞控制和流量控制.可以得出一个式子

发送方窗口的最大值 = Min(rwnd, cwnd);

TCP报文

很多人在学习TCP报文的时候直接看报文信息是有点不合理的,因为对于TCP报文为何被设计成现在的样子没有一个清楚的认识,只是单纯记住其含义是没用的,应该理解TCP其工作的流程之后再回顾TCP报文含义就很明显了.

TCP-Header

如上图就是TCP报头的数据内容.这里挑出一些做解释

  • Window size(窗口大小), 这里的窗口大小就是流量控制和拥塞控制中所提到用来限制发送方发送数据的速率

  • PSH 6个标志位中的一位.根据上面讲的,通常应用层的数据到达TCP层都会进入发送缓存等待若干时间再发送.如果PSH=1那么这个数据报会被马上发送给对方,而不是进入发送缓存等待.同理对于接收数据也不会进入接收缓存而是直接交付给上层应用.

好了,关于TCP的理论知识点就到这里,虽然没有对header信息进行充分的说明.甚至连三次握手连接,四次握手断开都没有说明.但是如果理解了上面TCP工作的流程.对于header信息以及握手协议应该很容易就掌握.


JayChen
1k 声望104 粉丝

哒哒哒...我有一个漂亮的女票