协议簇: TCP 解析 - 数据传输

Oct 11, 2021

目录


简介


前面,我们分别介绍了 TCP 基础知识以及连接的建立和关闭,以及最重要的 Sequence Number 的概念. 本篇文章,我们来介绍一下 TCP 如何传输数据.


系列文章



数据传输


当一个 TCP 连接建立成功之后, TCP 段便可以在这条连接上双向传输. 由于底层网络的不稳定,TCP 段可能在传输过程中出错,TCP 协议会重传这些出错的 TCP 段以确保每个段都成功的发送到了对方. 这个过程依赖于 Sequence Number 机制, TCP双方都需要维护一系列连接状态信息,以确保 Sequence Number 机制正常工作.

发送方使用 SND.NXT 字段记录下一个可用的 SEQ. 发送方将使用 SND.NXT 的值作为下一个发送的 TCP 段的 SEQ; 接收方使用 RCV.NXT 字段记录下一个应该收到的 TCP 段的 SEQ 值。发送方使用 SND.UNA 记录最早的已发送但还没有收到确认的 SEQ 值。 当所有数据包被成功发送并收到接收方的ACK时且当前网络空闲, SND.NXT, SND.UNA, RCV.NXT 三个字段的值应该是相同的.

当发送方构建了一个 TCP段并将它发送出去时, 发送方应该增加 SND.NXT 值。 当接收方接收到一个 TCP段时,接收方应该增加 RCV.NXT 并发送相应的 ACK. 当发送方接收到ACK 时,它应该增加 SND.UNA. 增加的幅度等于相应 TCP 段中所包含数据的长度. 注意,从连接建立成功之后,所有的段都应该包含 ACK 信息.


重传超时时间


TCP 会重传那些已经发送,但是一定时间之后还未收到ACK的段. 但是这个“一定时间”的大小的选择非常重要. 如果选择的太小,容易导致链接上充斥着冗余的数据(已经发送但是由于网络慢还未到达对方,但是发送方却由于重传超时时间已经到达,所以重发该段。 最终接收方会收到两个一摸一样的数据)。 如果太大,又会导致失败的数据包在失败之后等待很长时间才能被重传. 这种i情况下的结果是一样的,那就是 TCP 数据传输效率低下.

由于组成网络的物理链路形形色色,因此,没有一个固定的值能在各种情况下完美工作. 因此,这个超时时间应该是动态变化的.

RFC 中介绍了一种方案. 该方案如下:

发送数据,然后等待对应的 ACK,记录这个过程中所需要的时间。 我们称它为 Round Trip Time(RTT). 接着,使用 RTT 计算 Smoothed Round Trip Time(SRTT),计算方法如下:

SRTT = (ALPHA * SRTT) + ((1 - ALPHA) * RTT)

然后,使用更新之后的 SRTT 值计算 RTO(Retransmission timeout)的值,计算方法如下:

RTO = min [ UBOUND, max [ LBOUND, ( BETA * SRTT ) ] ]

其中,

UBOUND 和 LBOUND 分别代表超时时间的上限和下限.

ALPHA 是平滑因子(smoothing factor, 比如, 0.8 - 0.9)

BETA 是延迟方差因子 (delay variance factor, 比如, 1.3 - 2.0)


窗口的控制


每个 TCP 段中都包含 Window 字段来通知对方当前接收方能接收的 SEQ 的范围.

使用一个较大的 Window 值,对方会发送更多的数据给接收方。 但是如果太多数据被发送过来,那么这些数据会被丢弃. 这种情况下,会导致额外的重传工作, 增大物理链路的负担; 使用一个较小的 Window 值,将会抑制发送发的发送速率,会导致传输速率低下。

当发送窗口为 0 的时候,发送方应该周期性的给接收方重传数据. RFC 中建议在这种情况下使用 2 分钟作为重传超时时间. 这种情况下的重传的意义是: 确保当接收方又可以接收数据的时候,这个状态能被通告给发送方。

当接收方的窗口大小为 0 时,接收到对方的TCP段后,必须回复相应的ACK, 这个ACK中包含接收方期待接收的 SEQ 值和窗口为 0 的信息.

窗口大小的控制严重的影响着 TCP 连接的数据传输效率。 RFC 中提出了一些建议:

  1. 较小的窗口值会影响发送效率。 因此,建议接收方延迟更新窗口,直到附加分配的大小达到 最大可能分配大小的 X % (x 的值为 20 - 40)

  2. 建议发送发尽量避免发送太小的段,而应该等到窗口的大小足够了再发送。 但是如果上层用户调用 了 push 接口, 此时应该直接发送数据而不必顾虑段的大小。

    注意, ACK 段应该总是被立即发送,不应该被推迟。

  3. TCP实现应该总是尝试使用大一些的窗口值


总结


至此, RFC 793 中描述的 TCP 介绍完毕。 这里忽略了接口定义的描述.

后续,我们会介绍更加直白的TCP,而不再基于 TCP 的规范。


END!


Tags