【lwip】12-一文解决TCP原理( 十 )

  1. TSval指明了发送端在发送TCP Segment时的Timestamp;接收端在对该TCP Segment做ACK时,将TSval值回显在TSecr字段中 。
    1. 注意:由于TCP连接是双向的,接收端在ACK中回显TSecr时,也会把自己当前的Timestamp放入TSval字段 。
  2. Timestamp是一个随时间单调递增的值,由于TCP接收端只需要在ACK中将TSval简单地回显,因此通信双方并不需要进行时间同步等操作 。
  3. 通过Timestamp Option,发送端再也不需要在内存中保存发送Segment的时间了,只需要将其放入TSval,然后接收端将其回显在ACK Segment即可 。当发送端收到ACK Segment后,取出TSscr,和当前时间做算术差,即可完成一次RTT的测量 。
  4. 若非通过Timestamp Option来计算RTT,大部分TCP实现只会以“每个Window采样一次”的频率来测算RTT 。因此通过Timestamp Option,可以实现更密集的RTT采样,使RTT的测算更精确 。
Timestamp Option还能防止序列号回绕(PAWS) 。
序列号回绕冲突只会出现在高速连接上 。
序列号回绕冲突是指序列号seq[0,2^32],即是最大4G 。如果在高速的连接中,某段数据A因为路由问题出现重传(此时网络是可能出现2个以上时间段A),收到一个时间段A后继续接收 。seq溢出,轮回第二次序列号seq[0,2^32],如果此时上一轮回重传的数据段A也到达了,那怎么判断当前序列号seq是本次轮回的还是上次轮回的?(当然,一次seq的轮回需要在MSL内,否则这个报文段在它的TTL到期时会被某个路由器丢弃)
Timestamp Option能解决这个冲突 。
参考以下例子来理解:
  1. 假设TCP Window Size为1GB(使用Window Scale),发送者每发送一个Window的数据Timestamp值加100,数据的发送情况如下所示:
时间点发送数据量Seq NumTimestamp接收10G:1GOG:1G0~100OK21G:2G1G:2G100~200其中某些segment丢包后重传(重传后,网络上可能会出现多个这个数据段的包;也就是说可能会因为网络延迟原因,接收端会收到多个这个时间段的包 。)32G:3G2G:3G200~300OK43G:4G3G: 4G300~400OK54G:5G0G:1G400~500OK65G:6G1G:2G100~200、500~600接收500~600的包 。丢弃时间戳为100~200的包,因为从400开始序列号seq就已经开始回绕了 。在时间点2的时候,发生了丢包,然后重传 。
在时间点5,序列号开始回绕 。
在时间点6,已经被认为“丢包”的Segment延迟到达了 。
那怎么判断这个序列号seq为[1G:2G]的报文是上一轮回的还是现在需要接收的?
通过Timestamp Option字段的时间戳去区别 。由于最近生效的时间戳都超500了 。所以比这个时间戳前的字段都视为过期字段,PAWS机制将其丢弃 。
  • 注意理解这句话 。窗口1GB,说明没有收到确认的数据后面最多能发送不超过1GB的数据 。看上表,时间点5都已经接收完毕了,说明时间点5之前的数据都已经全部接收完了 。后面重传只会出现在[5G:6G]中间 。如果这里收到的数据的时间戳比时间点5的时间戳500还要少,说明是过期重传的数据,我们不需要 。
  • 最近有效的时间戳:参考下图理解 。所以只要收到的数据的时间戳少于有效时间戳,就视为过期数据 。

【lwip】12-一文解决TCP原理

文章插图
12.10.5 UTOUTO:User Timeout (UTO) Option
UserTimeout值表明了TCP发送者等待ACK的时间,如果在指定时间内没收到ACK,就会认为对端挂掉 。
对于传统TCP(RFC 793)而言,UserTimeout是本地配置的 。
RFC 1122建议,当TCP重传3次后,应该通知应用程序,100s后,应该删除连接 。
通过UTO,可以让TCP将UserTimeout值“告知”给对端,UTO格式如下所示:
Kind(28)Length(4)G bit(Granularity bit)UserTimeout

经验总结扩展阅读