zoukankan      html  css  js  c++  java
  • TCP首部的TimeStamp时间戳选项 转载

    TCP应该是以太网协议族中被应用最为广泛的协议之中的一个,这里就聊一聊TCP协议中的TimeStamp选项。这个选项是由RFC 1323引入的,该C建议提交于1992年。到今天已经足足有20个年头。只是相信大部分程序员对这个建议还是相当陌生。

    要理解为啥须要用TimeStamp选项。还须要从TCP协议的几个基本设计说起。

    TCP协议的几个设计初衷。以及引发的问题:
    1. 协议规定收端不须要响应每个收到的数据报文,仅仅须要收到N个报文后,向发端回复一个ack报文就可以。


        这种规定是为了提高通讯的效率,可是也引入了几个问题:
        A. 发端发出报文后,究竟多久可以收到ack是不确定的。
        B. 万一ack报文丢失了。推断须要重发的timeout时间也非常难确定。
    2. TCP报文中,标示Sequence号的地址长度为32位。
        这就限制了发端最多一次发送2^30长度的数据。就必须等待ack信号。为啥呢?在这个链接里有一些具体的讨论。
        然而对于超快速以太网(1000M以至于10G),这样会影响TCP连接的转发效率。


    为解决上面提到的问题,TimeStamp选项主要有两个用途:
    1. 測量TCP连接两端通讯的延迟(Round Trip Time Measurement)
        有了RTTM机制。TCP的两端能够非常easy的推断出线路上报文的延迟情况。从而制定出一个优化的发包间隔和报文TimeOut时间,从而攻克了第一个问题。


    2. 处理Sequence号反转的问题(Protect Against Wrapped Sequence Numbers)。
        TCP收端收到一个数据报文后,会先比較本次收到报文的TimeStamp和上次收到报文的TimeStamp。假设本次的比較新,那么能够直接推断本次收到的报文是新的报文,不须要进行复杂的Sequence Number Window Scale计算。从而攻克了第二个问题。

    然而,RFC1323建议还存在一些隐患。


    建议中定义TimeStamp添加的间隔能够使1ms-1s。假设设备依照1ms的速度添加TimeStamp。那么仅仅要一个TCP连接连续24.8天(1ms*2^31)没有通讯,再发送报文,收端比較本次报文和上次报文TimeStamp的动作就会出错。(问题1)
    (注:TCP协议中并未定义KeepAlive。假设应用层代码不定义超时机制。TCP连接就永远不会中断。所以连续24.8天不通讯的情况是却有可能发生的。)
    引用Linux相关代码:((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) < 0)
    比方 tp->rx_opt.rcv_tsval = 0x80000020,       tp->rx_opt.ts_recent = 0x10
     ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) = (s32)0x80000010,是一个负数,必定小于0。

    假设解决这个问题1呢?
    已知依照RFC1323的规定。依照最快TimeStamp添加的速度,也须要24.8天TImeStamp才有可能发生反转。
    假设((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) < 0)推断成立,还能够再用本地收到报文的本地TimeStamp减去上一次收到报文的本地TimeStamp。假设时间大于24.8天,那么就是TimeStamp发生了反转;否则就不是反转的情况。这样做是不是就万无一失了呢?不一定。

    别忘了本地TimeStamp的计数器也是个32位,也可能会翻转的。(问题2)
    举个极端的样例:如果TCP两端设备的TimeStamp添加间隔不一致,A为1ms。B为10ms。

    TCP连接连续248天没有通讯;这个时候B向A发送了一个数据报文。

     
    此时B发送给A的TCP报文中的TimeStamp,正好发生了翻转。然而因为A的计数器是每1ms加一的,248天时间。A的计数器已经归零过5次了。这时候再用本地TimeStamp做推断还是错的。

    比較保险的做法是:
    假设TCP连接的速度不那么快(2^32/s),本地TimeStamp用最大间隔时间1S。从而规避了(问题2)


    假设TCP连接速度很快,1S的TimeStamp间隔就有些不合时宜了,能够选小一级,如100ms。假设这时候还会发生连续24800天(为啥是24800天呢)不通讯的情况,除了骂娘以外。我也没办法了。

  • 相关阅读:
    程序员眼中的 SQL Server-执行计划教会我如何创建索引?
    SQL Server死锁排查
    详解Java中的clone方法 -- 原型模式
    sql-索引的作用(超详细)
    java.util.ConcurrentModificationException 解决办法
    SqlServer索引的原理与应用
    数据库性能优化三:程序操作优化
    数据库性能优化二:数据库表优化
    数据库性能优化一:数据库自身优化(大数据量)
    SQL索引一步到位
  • 原文地址:https://www.cnblogs.com/tunian/p/9482414.html
Copyright © 2011-2022 走看看