TCP 窗口缩放、时间戳和 SACK( 三 )


TCP 时间戳最佳截止日期
用最简单的术语来说 ,TCP 时间戳 只是在数据包上添加时间戳 , 以解决由非常快速的序列号回绕引起的歧义 。 如果一个段看起来包含新数据 , 但其时间戳早于上一个在接收窗口内的数据包 , 则该序列号已被重新回绕 , 而“新”数据包实际上是一个较旧的重复项 。 这解决了即使在极端情况下重传的歧义 。
但是 , 该扩展不仅仅是检测旧数据包 。 TCP 时间戳的另一个主要功能是更精确的往返时间测量(RTTm) 。
需要准确的 RTT 估算
当两个对等方都支持时间戳时 , 每个 TCP 段都携带两个附加数字:时间戳值和回显时间戳 。
TCP Timestamp option (TSopt): Kind: 8, Length: 10+-------+----+----------------+-----------------+|Kind=8 | 10 |TS Value (TSval)|EchoReply (TSecr)|+-------+----+----------------+-----------------+1144准确的 RTT 估算对于 TCP 性能至关重要 。 TCP 会自动重新发送未确认的数据 。 重传由计时器触发:如果超时 , 则 TCP 会将尚未收到确认的一个或多个数据包视为丢失 。 然后再发送一次 。
但是 , “尚未得到确认” 并不意味着该段已丢失 。 也有可能是接收方到目前为止没有发送确认 , 或者确认仍在传输中 。 这就造成了一个两难的困境:TCP 必须等待足够长的时间 , 才能让这种轻微的延迟变得无关紧要 , 但它也不能等待太久 。
低网络延迟 VS 高网络延迟
在延迟较高的网络中 , 如果计时器触发过快 , TCP 经常会将时间和带宽浪费在不必要的重发上 。
然而 , 在延迟较低的网络中 , 等待太长时间会导致真正发生数据包丢失时吞吐量降低 。 因此 , 在低延迟网络中 , 计时器应该比高延迟网络中更早到期 。 所以 , TCP 重传超时不能使用固定常量值作为超时 。 它需要根据其在网络中所经历的延迟来调整该值 。
往返时间的测量
TCP 选择基于预期的往返时间(RTT)的重传超时 。 RTT 事先是未知的 。 它是通过测量发送的段与 TCP 接收到该段所承载数据的确认之间的增量来估算的 。
由于多种因素使其而变得复杂 。

  • 出于性能原因 , TCP 不会为收到的每个数据包生成新的确认 。 它等待的时间非常短:如果有更多的数据段到达 , 则可以通过单个 ACK 数据包确认其接收 。 这称为 “累积确认”(cumulative ACK)
  • 往返时间并不恒定 。 这是有多种因素造成的 。 例如 , 客户端可能是一部移动电话 , 随其移动而切换到不同的基站 。 也可能是当链路或 CPU 的利用率提高时 , 数据包交换花费了更长的时间 。
  • 必须重新发送的数据包在计算过程中必须被忽略 。 这是因为发送方无法判断重传数据段的 ACK 是在确认原来的传输数据(毕竟已到达)还是在确认重传数据 。
最后一点很重要:当 TCP 忙于从丢失中恢复时 , 它可能仅接收到重传段的 ACK 。 这样 , 它就无法在此恢复阶段测量(更新)RTT 。 所以 , 它无法调整重传超时 , 然后超时将以指数级增长 。 那是一种非常具体的情况(它假设其他机制 , 如快速重传或 SACK 不起作用) 。 但是 , 使用 TCP 时间戳 , 即使在这种情况下也会进行 RTT 评估 。
如果使用了扩展 , 则对等方将从 TCP 段的扩展空间中读取时间戳值并将其存储在本地 。 然后 , 它将该值作为 “回显时间戳” 放入发回的所有数据段中 。
因此 , 该选项带有两个时间戳:它的发送方自己的时间戳和它从对等方收到的最新时间戳 。 原始发送方使用 “回显时间戳” 来计算 RTT 。 它是当前时间戳时钟与 “回显时间戳” 中所反映的值之间的增量 。
时间戳的其他用途
TCP 时间戳甚至还有除 PAWS( 防止序列号回绕(Protection Against Wrapped Sequences)) 和 RTT 测量以外的其他用途 。 例如 , 可以检测是否不需要重发 。 如果该确认携带较旧的回显时间戳 , 则该确认针对的是初始数据包 , 而不是重新发送的数据包 。


推荐阅读