原文转自:http://www.cnblogs.com/lovemyspring/articles/4271716.html

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的两端可以很容易的判断出线路上报文的延迟情况,从而制定出一个优化的发包间隔和报文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天呢)不通讯的情况,除了骂娘以外,我也没办法了。

TCP/IP协议栈中的TimeStamp选项的更多相关文章

  1. TCP/IP协议栈 --- 网络层(IP 首部 和分片)

    IP 是TCP/IP协议栈中重要的层次, TCP UDP ICMP IGMP都是依赖IP层进行传输的.首先它是一种不可靠,无连接的协议.不可靠:它不保证IP包能正确到达目的地,无连接:表示IP并不会维 ...

  2. TCP/IP协议栈概述及各层包头分析

    TCP/IP协议栈中各层包头的分析 Protocol列表示的是该数据包最高层对应的协议,Length列表示该包的长度(包括从底层的协议到最高层的协议,其中包头一般是,链路层14字节,IP20字节,TC ...

  3. TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现

    题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...

  4. TCP/IP协议栈在Linux内核中的运行时序分析

    网络程序设计调研报告 TCP/IP协议栈在Linux内核中的运行时序分析 姓名:柴浩宇 学号:SA20225105 班级:软设1班 2021年1月 调研要求 在深入理解Linux内核任务调度(中断处理 ...

  5. 【转】TCP/IP协议栈及OSI参考模型详解

    OSI参考模型 OSI RM:开放系统互连参考模型(open systeminterconnection reference model) OSI参考模型具有以下优点: 简化了相关的网络操作: 提供设 ...

  6. UNIX/Linux网络编程基础:图解TCP/IP协议栈

    目录 1.主机到网络层协议:以太网协议 2.IP协议 3.网际控制报文协议(ICMP) 4.传输控制协议(TCP) 5.用户数据报文协议(UDP) 6.流控制传输协议(SCTP) 7.地址解析协议(A ...

  7. TCP/IP协议栈与数据包封装+TCP与UDP区别

    ISO制定的OSI参考模型的过于庞大.复杂招致了许多批评.与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用.如图2-1所示,是TCP/IP参考模型和OSI参考模型的对比示意图. T ...

  8. TCP/IP协议栈及OSI参考模型详解

    OSI参考模型 OSI RM:开放系统互连参考模型(open systeminterconnection reference model) OSI参考模型具有以下优点: 简化了相关的网络操作: 提供设 ...

  9. linux OSI七层模型、TCP/IP协议栈及每层结构大揭秘

    学习Linux,就算是像小编我这样的小萌新,也知道OSI模型.什么?!你不知道!!! 好吧,这篇秘籍拿走,不谢~~~ 一.两个协议 (1)OSI 协议模型(7层)国际协议    PDU:协议数据单元对 ...

随机推荐

  1. MySQL 统计上一周从周一到周日的用户

    这个功能按理说很常见,奇怪的是很难搜索到一个合适的.稍微整理了下,具体的就不展开了,注意这个表中的时间为毫秒,这条语句拷贝复制就能用.照顾大部分的无脑码农. SELECT case when FROM ...

  2. Java 之 Cookie

    Cookie 一.会话概述 1.会话:一次会话中包含多次请求和响应.       一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止. 2.功能: 在一次会话的范围内的多次请求间 ...

  3. ubuntu16.04安装openssh中报错解决

    在使用apt-get直接进行安装时会报错: sudo apt-get install openssh-server 正在读取软件包列表... 完成 正在分析软件包的依赖关系树       正在读取状态 ...

  4. CCProxy代理

    只要局域网内有一台机器能够上网,其他机器就可以通过这台机器上安装的CCProxy来代理共享上网,最大程度的减少了硬件费用和上网费用.只需要在服务器上CCProxy代理服务器软件里进行帐号设置,就可以方 ...

  5. Android为TV端助力之弹出软键盘方式

  6. 结对项目(python) 黄浩伟 黄飞越

    作者:黄浩伟 黄飞越  一 .Github项目地址: https://github.com/Flying123haha/123.git 二.psp表格: PSP2.1 Personal Softwar ...

  7. idea安装与注册码破解

    idea安装与注册码破解 https://www.cnblogs.com/jajian/p/7989032.html

  8. Python学习日记(二十六) 封装和几个装饰器函数

    封装 广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见 私有属性 私有属性表示方式即在一个属性名前加上两个双下划线 cla ...

  9. App抓包代理设置

    1.设置Fiddler 打开Fiddler,Tools  -->  Fiddler Options  -->  HTPS (配置完后记得要重启Fiddler) 选中"Decrpt ...

  10. string长度问题

    原文地址: https://toutiao.io/shares/2029578/url String是Java中很重要的一个数据类型,除了基本数据类型以外,String是被使用的最广泛的了,但是,关于 ...