tcp

重传机制

方式

  • 超时重传

    • 概念

      • 发送数据时设定一个定时器,若在指定时间内没有收到应答报文,就会重发数据
    • 发生超时重传的时机

      • 数据包丢失
      • 确认应答丢失
    • 超时时间RTO选择

      • 略大于RTT
      • 重传超时策略:超时时间间隔加倍
  • 快速重传

    • 概念

      • 发送方可以一次发送多个数据包,若中间的某个数据包丢失了,接收方会一直回复这个丢失的数据包应答报文,接收方若收到三次这个数据包的应答报文,就知道该报文还没有被接收方收到,可以重传这个数据包
    • 问题

      • 因为接收方对后续的数据包也返回了丢失的那个应答报文,所以发送方不知道后续的数据包是否丢失,也就不知道应该重传丢失的数据包还是把后续的数据包都重传
  • SACK

    • 概念

      • 选择性重传,解决快速重传不知道重传哪些报文的缺点
    • 实现方式

      • 在tcp头部“选项”字段里加一个SACK,将缓存的地图发送给发送方,这样发送方就知道哪些数据接收方收到了,哪些数据接收方没有收到,以便重传接收方没有收到的数据
    • 参数

      • 要开启SACK,需要发送方和接收方都支持:net.ipv4.tcp_sack,linux2.4以后默认打开
  • D-SACK

    • 概念

      • 对SACK的扩展,通过SACK告诉发送方哪些数据被重复接收了
    • 实现方式

      • 若有发送方有重复发送数据包,会通过SACK告诉发送方这这个数据包已被发送过
    • 好处

      • 发送方能够知道是发出去的包丢了还是接收方发送的ACK丢了

        • SACK若告知这个包已被发送过,那么说明是接收方发送的ACK丢了
      • 发送方可以知道发出去的数据包是否被网络延迟了

        • 发送方在延迟之后会重发数据包,之前的数据包若一段时间后到达了接收方,接收方返回的应答报文中能看到该数据包已经被接收了,是个重复的报文,说明被网络延迟了,而重发的数据包已被收到

序列号与确认应答(ACK)保证了tcp的可靠传输

滑动窗口

引入原因

  • 每发送一个数据都需要进行确认应答,收到了再发送下一个,效率比较低。在窗口大小限制范围内,可以无需等待上一个数据包应答,就可以继续发送下一个数据包

错误处理

  • 累计应答

    • 发送数据包丢失

      • 若发送方发送了一批数据包,中间的某个数据包丢失,那么接收方回复应答时ACK会回复丢失的那个数据包,这样接收方就知道丢失的数据包是哪一个,因此可以重新发送;
    • 应答报文丢失

      • 若接收方返回的这一组数据包中,某一个应答报文丢失了,只要最后一个应答报文发送成功了,接收方就知道这个数据包的其实是收到了的

窗口大小

  • tcp头里的字段window

    • 接收方通过这个字段告诉接收方自己还有多少缓冲区可以接收数据,发送方就可以根据接收方的处理来发送数据,以免导致接收方处理不过来,因此窗口的大小是由接收方决定的
  • 接收方和发送方的窗口

    • 接收方和发送方的窗口大小基本相等,因为发送方的窗口大小取决于接收方,当接收方处理能力快,窗口变大,通过tcp报文中的window字段告诉接收方,若传输过程中出现了延迟,所以这时两个窗口大小不一致

拥塞控制

概念

  • 流量控制是避免发送方填满接收方的缓存,但若因为其他主机之间的通信造成网络拥堵,会有超时和丢包发生,这样会导致重传 ,网络负担会更大,进入恶性循环,所以tcp不能忽略网络上发生的事,当网络发生拥堵时,它会降低数据的发送量。拥塞控制的目的就是避免发送方的数据填满整个网络

拥塞窗口cwnd

  • 发送窗口swnd和接收窗口rwnd是约等于的关系,有了拥塞窗口的概念后,发送窗口swnd=min(cwnd, rwnd)

    • 网络中没有出现拥塞,cwnd会增大,反之会减小
  • 判断网络拥塞的方法

    • 发生超时重传
  • 相关算法

    • 慢启动

      • tcp刚建立连接完成,会有个慢启动的过程,一点一点提高发送数据包的数量
      • 每接收到一个ack,cwnd大小就会加1,初始化时,cwnd大小为1,即cwnd大小按指数级增长
      • ssthreshold,slow start thresold,慢启动门限

        • 当cwnd < ssthreshold时,会采用慢启动算法
        • 当cwnd >= ssthreshold时,会使用拥塞避免算法
    • 拥塞避免

      • 每收到一个ack,cwnd增加1/cwnd。即囤积了cwnd这么多个包后,一次性发送过去。之后都会这样发送,cwnd按线性增长
      • 当一直这么增长,会慢慢进入拥塞状况,于是开始出现丢包现象,这时需要对丢失的数据进行重传,当触发了重传机制也就进入了拥塞发生算法
    • 拥塞发生

      • 超时重传

        • ssthreshold设为cwnd/2
        • cwnd设为1
        • 即一旦发生超时重传就重新进入慢启动
      • 快速重传

        • 当接收方发现丢了一个中间包时,会发送三次丢失包的ack,发送方收到后就会快速重传丢失的包
        • tcp认为这时候拥塞并不严重,只丢了一小部分包,于是

          • cwnd = cwnd/2
          • ssthreshold变为cwnd
        • 然后进入快速恢复算法
    • 快速恢复

      • cwnd = ssthresold+3
      • 重传丢失的数据包
      • 如果再收到重复的ack,那么cwnd+1
      • 收到新的ack后,cwnd变为ssthreshold,然后进入拥塞避免算法

流量控制

概念

  • 流量控制是基于滑动窗口实现的,tcp通过让接收方指明希望从发送方接收的数据大小(窗口大小)来进行流量控制

问题

  • 描述

    • 接收方收到了太多数据,暂时不能接收数据了,于是返回了window大小为0
    • 发送方发现window大小为0,于是暂时不再发送数据包了
    • 接收方处理完数据,可以继续处理了,于是在之前已处理完的数据包的应答报文中更新窗口大小,但是该应答报文丢失了,导致接收方没能收到,于是就一直不发送新的数据包了,出现了死锁
  • 解决方法

    • tcp为每个连接设定一个持续计时器,只有发起连接的一方从对方收到零窗口通知,就启动计时器;如果持续计时器超时,就会发送窗口探测报文,对方会给出自己现在接收窗口的大小
    • 窗口探测次数一般为3次,每次大约30-60秒,如果三次后窗口还是0,有的tcp实现会发起RST报文来中断连接

糊涂窗口综合症

  • 发送方

    • 发送方虽然知道窗口很大,但是每次都只发送很少的数据
  • 接收方

    • 接收方太忙,每次都只能从window中取出很少的数据,然后通知发送方,这样发送方每次也只发送很少的数据
  • 问题

    • 每次都只传输小包,效率低
  • 解决方法

    • 让接收方不通知小窗口给发送方

      • 当窗口大小小于min(mss,(缓存空间/2))时,就会向发送方通知窗口为0,阻止发送方后续发送数据过来

        • 注mss,Maximum Segment Size,最大报文长度,MSS是TCP报文段中的数据字段的最大长度,不包括TCP首部的长度
    • 让发送方不发送小包

      • Nagel算法

        • 发送条件

          • 等到窗口大小>=mss或数据大小>=mss
          • 收到之前发送数据的ack应答
        • 满足发送条件的两点才会发送
        • 设置关闭

          • Nagel算法默认开启,若想要关闭,需要在socket设置TCP_NODELAY来关闭。没有全局参数,需要每个应用根据自己的特点来关闭

byte
106 声望13 粉丝

引用和评论

0 条评论