在最开始介绍TCP的时候,我们就介绍了TCP的三个特点,分别是面向连接、可靠、字节流式。前面内容我们已经介绍过了TCP的连接管理,接下来的这部分内容将会介绍与TCP可靠性强关联的TCP重传。

很多网络协议都提供了checksum或者CRC手段来检测收到的数据包是否发生错误,但是检测到数据包错误后很多协议都不会进行重传等操作来可靠的修复错误。例如常见的IP和UDP协议完全没有重传,对于链路层的以太网协议,虽然有重传操作但是尝试若干次重传还没有成功会也会放弃(CSMA/CD)

经过N多专家前扑后继的研究,在目前的信息论(information theory)和编码理论(coding theory)中,主要有两种方式用来保证可靠的传输

1、通过传输的数据包中增加冗余的error-correcting codes来修复传出错误的报文,这种方式中接受端在接收到报文的时候,如果报文中有少量的bit传输错误,接收端可以通过冗余数据恢复出正确的数据包。

2、使用ARQ(Automatic Repeat Request)机制来提高数据传输的可靠性,ARQ机制需要发送端重复发送传输错误的数据包直到接收端接收到正确的数据包为止

当前也有把这两种方式结合起来一起使用的协议,比如在LTE通信中,RLC层使用ARQ,MAC层使用HARQ(HARQ就是上面两种方式的综合体,先通过error-correcting codes来尝试修复传输错误的报文,如果修复失败则进行ARQ过程)。我们接下来要讲到的TCP协议则使用ARQ的方式。

来解决丢包和比特错误两类问题最简单的方式就是重新发送出错的数据包,这就需要知道

  • 接收端是否已经接收到对应的数据包。这个可以通过ACK(acknowledgment)来反映接收端接收到数据包的情况。但是这个又带来其他小问题比如发送端应该等待ACK确认包多长时间?如果超过这个时间发送端就认为数据包丢失而重新发送这个数据包。这个时间就叫做RTO(Retransmission Timeout),RTO应该根据环回时间RTT(round-trip-time)来估计。环回时间应该包括三部分:数据包传送过的时间,接收端处理这个数据包并产生ACK的时间,ACK确认包返回的时间。但是RTT这个时间是随着网络状况动态变化的,网络负载较重产生拥塞的时候,RTT就会变大,因此发送端就需要一种方式来动态估计这个RTT时间,这个过程就叫做round-trip-time estimation。这个估计过程是一个统计过程,真实的RTT应该比较接近这个统计平均值。另外一个问题是如果ACK报文丢失怎么办?如果接收端回复的ACK报文丢失,这又可以分为两种场景,一是后面的ACK报文在发送端RTO超时前到达发送端,发送端通过这个ACK报文可以得知之前的报文接收端已经收到。另外一种情况就是RTO超时前,没有收到后续的ACK报文,发送端则可以直接重传没有收到ACK的报文,这样接收端会接收到重复的TCP报文,接收端可以丢弃重复的报文。

  • 接收端接收到的数据包和发送端发送的数据包是否一致。一般来说有两种方式,一种是CRC,另外一种是checksum,在TCP协议中通过checksum机制检查比特错误。当TCP的checksum校验失败的时候,接收端并不会发送ACK给发送端。对于数据完整性要求较高的应用,应该在应用层添加更可靠的校验方式。

当TCP发送端每次发送一个数据包然后等待ACK的时候(即停等式 stop and wait),这种场景下TCP对网络带宽的利用率非常低,因此为了提高带宽利用率,允许TCP在没有收到ACK报文的情况下发送其他数据包。当多个数据包同时在网络中传输的时候,问题会变得更加复杂,比如发送端必须缓存还没有被接收端ACK的报文,当发送端速度低于接收端速度时候发送端需要降低TCP发送速度等等。

TCP主要有两种重传方式,上面我们介绍的是基于定时器的重传(timeout or timer-based retransmission),这种重传方式是发出去的数据在RTO超时后还没有收到对应的ACK就会进行超时重传。另外TCP还有一种基于ACK报文结构顺序的重传,这种重传叫做快速重传(fast retransmission或者fast retransmit),当TCP注意到累计ack(即TCP头中的ack number)不再推进或者接收端通过SACK信息指示发送端接收端存在洞(hole)时候就会触发发送端的重传,通常来说快速重传比超时重传更高效。另外谷歌还对快速重传提出了一种改进的重传机制,即早期重传(ER,Early Retransmit),还记得之前TFO也是谷歌提出来的吧。在这重传子系列内容中我们重点关注TCP如果判断丢包以及重传对应的数据包。至于发送多少数据包则等到我们后面的拥塞控制时候在来讲解。

补充说明:

1、从本章起,wireshark示例中server端的端口为9877,client端的端口为10000。其中client端使用raw socket编程来精确控制TCP的每个报文的,因此不要按照通常的协议要求来看待client的行为,我在/proc下添加了参数tcp_discard_on_port,设置后内核模块可以丢弃指定端口的tcp数据,当把tcp_discard_on_port设置为9877后,server发过来的TCP报文递交给raw socket后,内核TCP模块会直接丢弃这个tcp报文,而不会因为对应的端口没打开而回复RST消息。server端则是linux内核的原始实现,因为server的行为是与linux的实现一致的。我们在查看wireshark抓包图示的时候重点观察server的行为,不要纠结client的行为。

TCP系列11—重传—1、TCP重传概述的更多相关文章

  1. TCP的11种状态

    TCP的11种状态 TCP三次握手建立连接 Tcp头部 六个标志位中,我们要用到三个: SYN:SYN= 1 表示这是一个连接请求或连接接受报文.在建立连接时用来进行同步序号(个人理解是,在建立连接的 ...

  2. TCP的11种状态(转载)

    TCP的11种状态 TCP三次握手建立连接 Tcp头部 六个标志位中,我们要用到三个: SYN:SYN= 1 表示这是一个连接请求或连接接受报文.在建立连接时用来进行同步序号(个人理解是,在建立连接的 ...

  3. TCP系列21—重传—11、TLP

    一.介绍 Tail Loss Probe (TLP)是同样是一个发送端算法,主要目的是使用快速重传取代RTO超时重传来处理尾包丢失场景.在一些WEB业务中,如果TCP尾包丢失,如果依靠RTO超时进行重 ...

  4. TCP系列45—拥塞控制—8、SACK关闭的拥塞撤销与虚假快速重传

    一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作 ...

  5. TCP系列52—拥塞控制—15、前向重传与RACK重传拥塞控制处理对比

    一.概述 这里主要简单分析一个丢包重传并恢复的场景,通过不同的设置让这个相同的场景分别触发RACK重传和前向重传,通过对比说明以下问题: Forward Retransmit可以产生只有重传标记的数据 ...

  6. TCP系列22—重传—12、Forward Retransmit

    一.概述 forward retransmit相关的内容在RFC6675中有描述,可以参考RFC6675 section 4中NextSeg ()的定义.forward retransmit中文名可以 ...

  7. TCP系列16—重传—6、基础快速重传(Fast Retransmit)

    一.快速重传介绍 按照TCP协议,RTO超时重传是一个非常重要的事件,当RTO超时的时候,TCP会同时通过两种方式非常谨慎的降低发送数据包的速率,一种是基于拥塞控制削减发送窗口的大小,另外一个是通过指 ...

  8. TCP系列24—重传—14、F-RTO虚假重传探测

    一.虚假重传 在一些情况下,TCP可能会在没有数据丢失的情况下初始化一个重传,这种重传就叫做虚假重传(Spurious retransmission).发生虚假重传的原因可能是包传输中重排序.传输中发 ...

  9. TCP系列18—重传—8、FACK及SACK reneging下的重传

    一.介绍 FACK的全称是forward acknowledgement,FACK通过记录SACK块中系列号最大(forward-most)的SACK块来推测丢包信息,在linux中使用fackets ...

随机推荐

  1. (转)Spring boot(一):入门篇

    https://www.cnblogs.com/ityouknow/p/5662753.html#!comments 构建微服务:Spring boot 入门篇 什么是Spring Boot Spri ...

  2. [Oracle] ROWNUM和分页

    rownum是oracle的一个伪劣,它的顺序依据从表中获取记录的顺序递增,这里要注意的是:由于记录在表中是无序存放的.因此你无法通过简单的rownum和order by的组合获得相似TOP N的结果 ...

  3. Visual studio 2010 OpenGL配置

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/niuxiunan/article/details/24557935 题记:今天同学问我关于OpenG ...

  4. DNS攻击

    DNS攻击 实验是基于Linux系统,配置了bind9服务的机器 大纲 本地修改Host文件重定向路径到指定地址 对User的DNS查询进行欺骗攻击 在同一局域网下,对DNS服务器的DNS查询进行欺骗 ...

  5. 修改sqlserver的数据库名、物理名称和逻辑文件名

    作者:dym0080 来源:CSDN 原文:https://blog.csdn.net/dym0080/article/details/81017777 版权声明:本文为博主原创文章,转载请附上博文链 ...

  6. 【转】Kaggle注册问题-验证码和手机短信

    注册和登录Kaggle时验证码无法显示问题 参考:https://blog.csdn.net/zhuisaozhang1292/article/details/81529981 应用FQ软件需要时时关 ...

  7. JS常见的小代码

    一:去掉数组里面的重复项. 比如 如下一个数组:var arr = [1,2,4,3,4,3]; 我想要得到数组 [1,2,4,3].为这样的 写一个函数去掉重复的项. var unique = fu ...

  8. Android学习之触点事件的处理

    知识点: 1. Android开发中的运动事件:触摸屏(TouchScreen)和滚动球(TrackBall) 2.对运动事件的处理:MotionEvent 3.触摸时必发的三个MotionEvent ...

  9. Java发送QQ邮件

    面试的时候被问到这个问题,别人问我用Java发过邮件没有,被问得一脸懵逼.然后就研究了一下,不是很难,按照网上的方法折腾了几天就搞出来了. 首先,使用QQ邮箱发送邮件之前需要在邮箱里面配置,开启pop ...

  10. android ImageLoader加载本地图片的工具类

    import android.widget.ImageView; import com.nostra13.universalimageloader.core.ImageLoader; /** * 异步 ...