zoukankan      html  css  js  c++  java
  • TCP协议下

    上篇讲到了TCP 的特点,TCP协议的包头以及TCP 协议的三次握手和四次挥手等,今天了解一下TCP 是如何做到可靠的,怎样保证顺序,如何解决拥塞问题的。
     
    TCP是如何做到可靠的?
     
    TCP的逻辑也很简单,上一个收到了应答,再发送下一个。
    为了保证顺序性,每一个包都有一个 ID。在建立连接的时候,会商定起始的 ID 是什么,然后按照 ID 一个个发送。为了保证不丢包,对于发送的包都要进行应答,但是这个应答也不是一个一个来的,而是会应答某个之前的 ID,表示都收到了,这种模式称为累计确认或者累计应答(cumulative acknowledgment)。
     
    为记录所有发送和接收的包,TCP的发送端和接收端都需要缓存来保持这些记录,发送端的缓存里按照ID一个一个排列,根据处理的情况分成四个部分。 
    1. 已经确认发送的。
    2. 发送了但是还没收到ACK。
    3. 没有发送但是已经等待发送的。
    4. 没有发送,暂时还不会发送的。
     在TCP 中,接收端会给发送端报一个窗口的大小,叫Advertised windows。这个窗口的大小应该等于第二部分加上第三部分,超过这个窗口的接收端就处理不了啦。
    在发送端维持下面的数据结构:

    对于接收端来讲,它的缓存内容简单一些,有三个部分:

    1. 接受并且确认过的
    2. 还没接收,但是马上能接收的。
    3. 还没接收,也没法接收的

    AdvertisedWindow = MaxRcvBuffer - (nextByteExpected - LastByteRead).

    TCP 协议在接收端和发送端有了这样两个队列窗口就能解决丢包问题和顺序问题了。结合这两个图,再配合一个例子就能说明TCP 是如何做到的了。

    在发送端这边,1、2、3是已经发送并确认接收的了。456789 是发送了但是还没有确认接收的,10、11、 12 是还没有发送的。13、14、15 是接收方没有空间,不准备发送的。

    在接收端这边,12345 是已经接收完成并ACK 的,但是程序还没有读取。6、7是等待接收的,8、9是已经收到了的但是还没有ACK。

    发送端和接收端当前的状态如下:

    • 1、2、3 没有问题,双方达成了一致。
    • 4,5 接收方回ACK了,但是发送方还没有收到。
    • 6,7,8,9 发送端已经发送,但是8,9到了,6,7没到,出现乱序,所以先缓存没法ACK。

    上面的4,5 包情况就是如果在规定时间还没收到接收端的ACK就重新发送,这个方法就是 超时重试。在网络传输中,顺序问题和丢包问题都有可能发生,所以要有确认与重发机制。重试的时间要大于往返时间RTT,TCP采用RTT的时间,然后进行加权平均,算出一个值,因为网路状况不断变化,算出的这个值也要不断变化。由于重传时间是不断变化的(因为网络可能时好时坏),所以有了 自适应重传算法:TCP 的策略是超时间隔加倍,每当遇到一次超时重传的适合,都会将下一次超时时间间隔加倍。

     
    流量控制问题
     
    前面我们说了,发送端的窗口是由接收端缓存的大小设定的。在发送端,如果5 这个包接收到ACK了,就可以把LastByteAcked 向右移动一个,这时窗口大小不变,AdvertisedWindow也要向右移动一个,所以发送端就可以将14 发送了。如果5没收到的话就不会向右移动窗口。
     
    如果接收方处理的实在太慢,发送端可以通过确认信息修改窗口的大小,甚至可以为0,也就是说发送端不再发送数据了。在接收端这边,应用程序处理“接收已确认”的数据速度太慢,确认接收的包会越来越多,直到NextByteExpected 和 MaxRcvBuffer之间的窗口越来约小,直到为0。
     
    出现这种情况的话,发送端会定时发送窗口探测数据包,看是否有机会调整窗口的大小。接收端这边不会刚空出一个字节就通知发送方,而是等到缓冲区空出一半的时候才更新窗口的信息。
     
    拥塞控制
     
    拥塞控制的问题,也是通过窗口的大小来控制的,滑动窗口rwnd是怕发送方把接收方缓存塞满,而拥塞窗口cwnd,是怕把网路塞满。
     
    通道的容量=带宽 * 往返延时
     
    设置发送窗口,使得发送但未确认的包为通道的容量,就能够撑满整个通道。
     
    如果在通道占满还继续发送的话,网路中的路由设备会丢掉处理不了的包。这个时候就不要再发送了,发送端会定时试探网络的环境,当网络环境变好的时候,发送的包很快有了回应ACK,就可以加快速度发送了。
     
    慢启动问题
    TCP协议要一点一点的试探网路的环境,发送数据量是逐步变大的。但是变大也有个上限,有一个值 ssthresh 为 65536,小于这个值传输速率指数增长,大于这个值线性增长。
     
    TCP拥塞控制的弊端。
    第一个问题是丢包并不代表着通道满了
    第二个问题是 TCP 的拥塞控制要等到将中间设备都填充满了,才发生丢包,从而降低速度,但这时已经晚了
     
    TCP BBR 拥塞算法,这个就更复杂了,以后有需要再深入研究吧。
     
    总结:
    顺序问题、丢包问题、流量控制都是通过滑动窗口来解决的,拥塞控制是通过拥塞窗口来解决的,
     
  • 相关阅读:
    数据库sql一些常考基础命令
    C# and .NET之父——传奇的anders hejlsberg
    数据库中3大范式的详解
    小胖求职记—求职中的技巧
    程序员们喜爱看的文章
    为什么世界上没有天才(转)
    C语言中system函数的使用
    关于DataGrid的知识和技巧
    分页
    在调用方法时产生异常的处理方法
  • 原文地址:https://www.cnblogs.com/mingjie-c/p/11391964.html
Copyright © 2011-2022 走看看