TCP的可靠传输、流量控制以及拥塞控制

254 阅读11分钟

我们开发的过程中,经常接触到http,但是对tcp的了解却很少,最近对TCP的理解发现要更加深入,而不只是三次握手和四次挥手,那么我们就来深入的研究下TCP吧。

一、TCP报文的介绍

TCP报文段分为首部和数据两部分。TCP的全部功能体现在首部的各个字段中,所以重点讲解下TCP报文的首部。以下就是TCP首部的各个字段的部分。

  • (1)、源端口和目的端口:各占2B
  • (2)、序号:占4B,TCP是面向字节流的(就是说TCP传送时是按照一个个字节来传送的),所以在一个TCP连接中传送的字节流需要编号,这样才能保证按序交付
  • (3)、确认号:占4B,接收端需要给发送端发送确认号,若确认号等于N,则表明到序号N-1为止的所有数据都已经正确收到。
  • (4)、数据偏移:占4位,表示首部长度,占4位可表示0001~1111一共15个状态,而基本单位是4B,所以数据编译确定首部最长为60B
  • (5)、保留字段:占6位,保留后面使用,目前为0
  • (6)、紧急URG:当URG=1时,表明紧急指针字段有效。紧急UDG和紧急指针要配套使用。紧急指针指向最紧急的报文段,最快传送,传送完了,然后TCP才告诉才告诉应用程序恢复到正常操作。
  • (7)、确认比特ACK:只有当ACK=1时,确认号字段才有效;当ACK=0时,确认号无效。TCP规定,一旦连接建立了,所有传送的报文段都必须把ACK置1
  • (8)、推送比特PSH:TCP收到推送比特置1的报文段,就尽快地交付给接收应用进程,而不再等到整个缓存都填满后再向上交付。
  • (9)、复位比特RST:当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或者其他原因),必须释放连接。
  • (10)、同步比特SYN:同步比特SYN置为1,表示这是一个连接请求或连接接受报文。
  • (11)、终止比特FIN: 释放一个连接,当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放传输连接。
  • (12)、窗口字段:占2B,窗口字段用来控制对方发送的数据量,单位为字节(B)。窗口字段明确指出了现在允许对方发送的数据量。
  • (13)、校验和字段:占2B,校验和字段检验的范围包括首部和数据两部分,在计算校验和时,和UDP一样,要在TCP报文段的前面加上12B的伪首部(只需将UDP伪首部的第4个字段的17改为6,其他和UDP一样)
  • (14)、紧急指针字段:占2B
  • (15)、选项字段:长度可变。TCP最初只规定了一种选项,即最大报文段长度MSS,
  • (16)、填充字段:为了使整个首部长度是4B的整数倍。

二、TCP可靠传输

  • 1·TCP数据编号与确认
    • TCP是面向字节的,TCP将所要传送的报文看成是字节组成的数据流,并使每一个字节对应于一个序号。在连接建立时,双方要商定初始序号。TCP每次发送的报文段的首部中的序号字段数值表示该报文段中的数据部分的第一个字节的序号。
  • 2.在使用TCP传送数据时,如果有一个确认报文段丢失了,会不会一定引起对方数据的重传?
    • 如果使用了累积确认就不一定。例如,现在采用累积确认,A发送了1、2、3、4、5号帧给B,但是ACK3丢失了(1和2号帧都接收到了,期望接收到3号帧)。此时发送方正准备重发1和2号帧,却接收到了ACK6,也就是1~5号帧对方都收到了,所以就不要重发了。
  • 3.选择确认SACK
    • 在后退N帧协议中,如果帧不按序到达,直接丢弃后面的,没有使用选择确认。在选择重传协议中,先把后面有序的帧存在接收缓冲区中,等到前面失序的帧到达后,一起按序交付,这里就用到选择确认SACK。
  • 4.TCP的重传机制
    • TCP每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到了规定时间还没有收到确认,那么就要重传该报文段。
    • TCP采用了一种自适应的算法:
      • 1)记录每个报文段发出的时间以及收到相应的确认报文段的时间。这两个时间之差就是报文段的往返时延。

      • 2)将各个报文段的往返时延样本加权平均,就得出报文段的平均往返时延(RTT)

      • 3)每测量到一个新的往返时延样本,就按下式重新计算一次平均往返时延

        RTT=(1-α)x(旧的RTT)+αx(新的往返时延样本)

      • 在上式中,0<=α<1,若α很接近于1,表示新算出的平均往返时延RTT和原来的值相比变化较大,即RTT的值更新较快。若选择α接近于0.则表示加权计算的RTT受新的往返时延样本的影响不大。即RTT的值更新较慢,一般推荐α取0.125 计时器的超时重传时间(RTO)应略大于上面得出的RTT。即RTO=βxRTT(其中β>1)

    • Karn算法:报文段每重传1次,就把RTO增大一些:新的RTO = γX(旧的RTO)
      • 系数γ的典型值为2,当不再发生报文段的重传时,才根据报文段的往返时延更新加权RTT和RTO的数值。
  • 5、往返时间RTT只是对传输层的TCP很重要,因为TCP要根据RTT的值来设置超时时间
  • 6、假定在一个互联网中,所有的链路都不出现差错,所有的结点也都不会发生故障。试问在这种情况下,TCP的“可靠交付”的功能是否就是多余的?
    • 不是多余的。TCP的“可靠交付”功能在互联网中起着至关重要的作用。至少在以下所列举的情况下。TCP的“可靠交付”是必不可少的。
      • 1)、每个IP数据报独立地选择路由,因此在到达目的主机时有可能出现失序
      • 2)、由于路由选择的计算出现错误,导致IP数据报在互联网中转圈.最后数据报首部中的生存时间TTL的数值下降到零,这个数据报在中途就被丢弃了。
      • 3)、在某个路由突然出现很大的通信量,以致路由器来不及处理到达的数据报,因此有的数据报被丢弃。

三、TCP流量控制

  • 1、流量控制就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞。利用滑动窗口机制可以很方便地在TCP连接上实现流量控制。 以上就是流量控制举例说明
  • 2、机制:TCP为每一个连接设有一个持续计时器。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1B的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。若窗口仍然是零,则收到这个报文段的一方就重新设置持续计时器。若窗口不是零,则死锁的僵局就可以打破了。
  • 3、可以用不同的机制来控制TCP报文段的发送时机
    • 第一种机制:TCP维持一个变量,它等于最大报文段长度(MSS)。只要缓存中存放的数据达到MSS字节时,就组装成一个TCP报文段发送出去
    • 第二种机制:由发送方的应用进程指明要求发送报文段,即TCP支持的推送(push)操作
    • 第三种机制:发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过MSS)发送出去。

四、TCP拥塞控制

  • 1、拥塞控制:在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生拥塞。出现资源拥塞的条件是:对资源需求的总和>可用资源
  • 2、拥塞控制与流量控制的性质对比:
    • 1)、拥塞控制所要做的只有一个目的,就是使得网络能够承受现有的网络负荷。
    • 2)、拥塞控制是一个全局性的过程,涉及所有的主机、所有的路由器以及与降低网络传输性能有关的所有因素。
    • 3)、流量控制往往指在给定的发送端和接收端之前的点对点通信量的控制
    • 4)、流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收
    • 5)、拥塞控制是很难设计的,因为它是一个动态的(而不是静态的)问题
    • 6)、当前网络正朝着高速化的方向发展,这很容易出现缓存不够大而造成分组的丢失。但分组的丢失是网络发生拥塞的征兆而不是原因。
    • 7)、在许多情况下,正是拥塞控制本身成为引起网络性能恶化甚至发生死锁的原因。
  • 3、拥塞控制又分为闭环控制和开环控制
    • 1)、开环控制方法就是在设计网络时事先将有关发生拥塞的因素考虑周到,力求网络在工作时不产生拥塞。
    • 2)、闭环控制是基于反馈链路的概念。属于闭环控制有以下几张措施:
      • (1)、监测网络系统以便检测到拥塞在何时、何地发生
      • (2)、将拥塞发生的信息传送到可采取行动的地方。
      • (3)、调整网络系统的运行以解决出现的问题。
  • 4、拥塞控制的4种算法:
    • 1)、接收端窗口rwnd:接收端根据其目前接收缓存大小所许诺的最新的窗口值,反映了接收端的容量。由接收端将其放在TCP报文的首部的窗口字段通知发送端
    • 2)、拥塞窗口cwnd:发送端根据自己估计的网络拥塞程度而设置的窗口值,反映了网络的当前容量。
    • 3)、发送端发送窗口的上限值应当取接收端窗口rwnd和拥塞窗口cwnd这两个变量中较小的一个,即 发送窗口的上限值=Min[rwnd, cwnd]
      • 当rwnd < cwnd时,发送窗口的上限值是接收方的接收能力限制发送窗口的最大值。
      • 当cwnd < rwnd时,发送窗口的上限值是网络的拥塞限制发送窗口的最大值。
      • 接收方总是有足够大的缓存空间,因而发送窗口的大小由网络的拥塞程度来决定,也就是说可以将发送窗口等同于拥塞窗口。
    • 4)、慢开始算法
      • (1)、在主机刚刚开始发送报文段时可先设置拥塞窗口cwnd=1,即设置为一个最大报文段长度MSS的数值。
      • (2)、在每收到一个对新的报文段的确认后,将拥塞窗口加1,即增加一个MSS的数值。即每收到一个对新的报文段确认后,将拥塞窗口加1,而第二次会收到2个确认,第三次会收到4个确认,依此类推,可以知道每经过一个传输轮次,拥塞窗口就加倍。
      • (3)、用这样的方法逐步增大发送端的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。
    • 5)、拥塞避免算法。
      • 为防止拥塞窗口cwnd的增长引起网络阻塞,还需要一个状态变量,即慢开始门限ssthresh,其用法如下:
        • 当cwnd < ssthresh时,使用慢开始算法
        • 当cwnd > ssthresh时,停止使用慢开始算法,改用拥塞避免算法。
        • 当cwnd = ssthresh时,即可以使用慢开始算法,也可以使用拥塞避免算法。
      • 其中拥塞避免算法的做法是,发送端的拥塞窗口cwnd每经过一个往返时延RTT就增加一个MSS的大小,通常表现为按线性规律增长。
      • 无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的发送窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
    • 6)、快重传算法
      • 要求接收方每收到一个失序的报文段后就立即发出重复确认,这样做可以让发送方及早知道有报文段没有到达接收方。发送方只要连续收到3个重复确认就应当立即重传对方尚未收到的报文段。
    • 7)、快恢复算法
      • (1)、当发送端收到连续3个重复的确认时,就执行“乘法减小”算法,把慢开始门限ssthresh设置为当前拥塞窗口的一半。但接下去不执行慢开始算法。
      • (2)、由于发送方现在认为网络很可能没有发生拥塞,所以现在不执行慢开始算法,即拥塞窗口cwnd现在不设置为1,而是将慢开始门限ssthresh设置为当前拥塞窗口的一半,然后开始执行拥塞避免算法(“加法增大”)使得拥塞窗口缓慢地线性增大。快恢复的具体算法如下:
        • 【1】、当发送端收到连续3个重复的ACK时,就重新设置慢开始门限ssthresh(拥塞窗口的一半)。
        • 【2】、与慢开始的不同之处是拥塞窗口cwnd不是设置为1,而是设置为新的ssthresh.
        • 【3】、若发送窗口值还允许发送报文段,就按拥塞避免算法继续发送报文段。

以上就是TCP的相关介绍,不难,但是很容易就忘记了,因为工作中比较少用到,所以只能记录下来,多查阅多看看。