在最开始介绍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. [java基础]一文理解java多线程必备的sychronized关键字,从此不再混淆!

    java并发编程中最长用到的关键字就是synchronized了,这里讲解一下这个关键字的用法和容易混淆的地方. synchronized关键字涉及到锁的概念, 在java中,synchronized ...

  2. 控件_AnalogClock

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...

  3. linuxserver本地和百度云备份脚本小试

    本地单文件上传脚本.命名uf 这是在本机上做的測试,利用bpcs_uploader脚本实现,仅仅是进行简单的封装.自己主动完好云端文件路径. 技术要点:使用dirname获取文件所在文件夹.使用pwd ...

  4. 生成条形码插件 条形码--JsBarcode

    每天学习一点点 编程PDF电子书免费下载: http://www.shitanlife.com/code 介绍一下在GitHub生成条形码的js插件→JsBarcode 条码支持的有: CODE128 ...

  5. 【转】mysql explain执行计划详解

      1).id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行,id列为null的就表是这是一个结果集,不需要使用它来进行查询.   2).select_type列常见的有: A:simp ...

  6. 课程设计小组报告——基于ARM实验箱的捕鱼游戏的设计与实现

    课程设计小组报告--基于ARM实验箱的捕鱼游戏的设计与实现 一.任务简介 1.1 任务内容 捕鱼游戏这个项目是一个娱乐性的游戏开发,该游戏可以给人们带来娱乐的同时还可以给人感官上的享受,所以很受人们的 ...

  7. metamask-mascara-在线钱包使用

    网址为:https://wallet.metamask.io 这是一个在线钱包,可以看见,它是一个测试版的 输入你自己设置的一个密码,然后create 接着就会进入下面这个页面,然后next: 然后a ...

  8. python 打印 emoji

    python 打印 emoji 如需转发,请注明出处:小婷儿的python  https://www.cnblogs.com/xxtalhr/p/10486506.html 一.Unicode字符集: ...

  9. odoo学习之弹框显示

    按条件隐藏: <xpath expr="//group[1]" position="attributes"> <attribute name= ...

  10. 使用自定义端口连接SQL Server的方法(转载)

    使用过SQL Server的人大多都知道,SQL Server服务器默认监听的端口号是1433,但是我今天遇到的问题是我的机器上有三个数据库实例,这样使用TCP/IP远程连接时就产生了问题.如何在Mi ...