原文转自: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. 使用cmd命令行登录mysql并查看mysql状态

    直接上代码,打开cmd命令窗口,进入mysql的安装目录(例如:cd  D:/lnmp/bin/mysql/mysql5.7.11/bin)输入: #mysql -u root -p Enter pa ...

  2. 82.使用vue后怎么针对搜索引擎做SEO优化?

    什么是SEO 搜索引擎优化(Search engine optimization,简称SEO),指为了提升网页在搜索引擎自然搜索结果中(非商业性推广结果)的收录数量以及排序位置而做的优化行为,是为了从 ...

  3. 【数据泵】EXPDP导出表结构

    [数据泵]EXPDP导出表结构(真实案例) BLOG文档结构图         因工作需要现需要把一个生产库下的元数据(表定义,索引定义,函数定义,包定义,存储过程)导出到测试库上,本来以为很简单的, ...

  4. MySQL DDL--MySQL 5.7版本Online DDL操作

    主键索引维护 1.新增主键索引 ## 可以使用ALGORITHM=INPLACE+LOCK=NONE方式,操作期间允许读写. ALTER TABLE tb001 ADD PRIMARY KEY (ID ...

  5. Gradle 使用教程之 Task 详解

    最近打算学习下 gradle 在 Android 中的使用,结果百度出来的文章都是介绍性文章,没啥干货.后来找到 gradle 官网教程,自己对着撸. Gradle 概述: Gradle 是一个基于 ...

  6. Linux操作系统故障排除之Grub信息被删除

    Linux操作系统故障排除之Grub信息被删除 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. [root@yinzhengjie ~]# hexdump -C /dev/sda - ...

  7. Layui外部js修改表格内容

    //测试修改数据的方法! var _tds=$(".layui-table-body.layui-table-main:eq(1) tr:eq(1)").children(); _ ...

  8. Oracle锁表与解锁 对象锁与解锁

    阅读目录 锁表与解锁 查看锁表进程SQL语句 解锁 对象锁与解锁 回到顶部 锁表与解锁 查看锁表进程SQL语句 select * from v$session t1, v$locked_object ...

  9. GO语言开发之路

    Go语言开发之路 介绍 为什么学习Go语言? 开发环境准备 从零开始搭建Go语言开发环境 VS Code配置Go语言开发环境 基础 Go语言基础之变量和常量 Go语言基础之基本数据类型 Go语言基础之 ...

  10. STLNormalFunc

    #include <iostream> #include <vector> using namespace std; void main_1() { vector<int ...