精华内容
下载资源
问答
  • TCP重传机制

    万次阅读 2018-09-18 21:47:57
    TCP使用两套独立的机制来完成重传,一是基于时间,二是基于确认信息的构成。  第一种基于时间的重传在其下的数据链路层、网络层乃至同层的UDP协议都有使用,即设置一个计时器来判断数据传输是否超时,当然它们...

           由于TCP的下层网络(IP)可能出现丢失、重复或失序的情况,TCP协议提供可靠数据传输服务。为保证数据传输的正确性,TCP会重传其认为已丢失(包括报文中的比特错误)的包。TCP使用两套独立的机制来完成重传,一是基于时间,二是基于确认信息的构成。

           第一种基于时间的重传在其下的数据链路层、网络层乃至同层的UDP协议都有使用,即设置一个计时器来判断数据传输是否超时,当然它们对于计时器时间的设定规则有所不同。本文主要聚焦于TCP的第二种重传机制。

    快速重传

           快速重传机制[RFC5681]基于接收端的反馈信息来引发重传,而非基于计时器超时重传。与超时重传相比,快速重传能更加及时有效地修复丢包情况。

           快速重传机制要求当接收到失序报文段时,TCP需要立即生成确认信息(重复ACK),并且失序情况表明在后续数据到达前出现了丢包,发送端的工作即为尽快填补丢包带来的数据段空缺。

           所谓重复ACK,举个例子,假设A与B之间建立连接,A向B发送数据,有4个TCP报文段,序列号分别为:N-1,N,N+1,N+2。再假设序列号N的报文段丢失(也许只是延迟到达),将会导致失序:N-1,N+1,N+2。此时接收端回复的ACK将会是N,N,N(接收到N-1的报文段后接收端认为下一个应该是N)。因此TCP等待一定数目的重复ACK(称为重复ACK阙值或dupthresh),来决定数据是否丢失并触发快速重传。通常这个阙值为常量3,但也有一些协议实现可基于当前的失序程度动态调节该值。

           快速重传算法可以概括如下:TCP发送端在观测到至少dupthresh个重复ACK后,即重传可能丢失的数据分组,而不必等到重传计时器超时。不采用SACK时,在接收到有效ACK前最多只能重传一个报文段。根据重复ACK推断的丢包通常与网络拥塞有关,因此快速重传也会触发拥塞控制机制。采用SACK(见下文),ACK可包含额外信息,使得发送端在每个RTT时间内可以填补多个空缺。

    SACK

           由于TCP采用累积ACK确认,因此TCP有时候并不能正确地确认之前已经接收的数据。由于接收的数据是无序的,所以接收到的数据的序列号也是不连续的。在这种情况下,TCP接收方的数据队列中会出现空洞的情况。因此在提供字节流传输服务时,TCP接收方需要防止应用程序使用超出空间的数据。一种方法是直接禁止交付存在空洞的数据,直到空洞被填补。而另一种方法则是使用SACK选项。

           如果TCP发送方能够了解接收方当前的空洞(以及序列空间中超出空洞的乱序数据块),它就能在报文段丢失或接收方遗漏时更好地进行重传工作。接收方通过SACK选项能够提供确认信息描述乱序数据,以帮助发送方有效地利用信息进行重传。

           SACK信息保存于SACK选项中,包含了接收方已经接收的数据块的序列号范围,每个范围被称作一个SACK块,由一对32位的序列号表示。因此,一个SACK选项包含了n个SACK块,长度为(8n+2)个字节,增加的2个字节用于保存SACK选项的种类与长度。由于TCP头部选项的空间有限,因此一个报文段中发送的最大的SACK块数目为3(假设使用了时间戳选项)。虽然只用SYN报文段才能包含“选择确认”选项,但是只要发送方已经发送了该选项,SACK块就能通过任何报文段发送出去。

    带选择确认的重传

           合理采用SACK信息能更快地填补数据空洞,且能减少不必要的重传,原因在于一个RTT内能获知多个空缺。当采用SACK时,一个ACK可包含3个告知失序数据的SACK信息,每个SACK信息包含32位的序列号,代表接收端存储的失序数据的起始至最后一个序列号(加1)。

    伪超时与重传

           在很多情况下,即使没有出现数据丢失也可能引发重传。这种不必要的重传称为伪重传(spurious retransmission),造成伪重传的主要原因是伪超时(spurious timeout),即过早判定超时,其他因素如包失序、包重复,或ACK丢失也可能导致该现象。在实际RTT显著增长以致超过了当前RTO时,就可能出现伪超时。

    包失序

           在IP网络中出现包失序的原因在于IP层不能保证包传输是有序进行的,但这种策略是有利的,因为IP可以选择不同的传输链路,合理利用现有链路。还有其他的原因,例如一些高性能路由器会采用多个并行数据链路进行分组转发,以及不同的处理延时也会导致包的离开顺序与到达顺序不匹配。

           当传输出现失序时,TCP可能会在某些方面受到影响。如果失序发生在反向(ACK)链路,就会使得TCP发送端窗口快速前移,接着又可能会收到一些显然重复而应被丢弃的ACK。由于TCP的拥塞控制行为,这种情况会导致发送端出现不必要的流量突发(即瞬时的高速发送)现象,影响可用网络带宽。

           如果失序发生在正向链路,TCP可能无法正确识别失序和丢包——数据的丢失和失序都会导致接收端收到无序的包,造成数据空缺。当失序程度不是很大时(如两个相邻的包交换顺序),这种情况可以迅速得到处理。反之,当出现严重失序时,TCP会误认为数据已经丢失,这就会导致伪重传。对此问题,可以设置一个合适的快速重传触发阙值来一定程度解决这一个问题。

    包重复

           IP协议可能出现将单个包传输多次的情况。例如,当链路层网络协议执行一次重传,并生成同一个包的两个副本。包的多次重复会使接收端生成一系列的重复ACK,这足以触发伪快速重传。使用SACK(特别是DSACK)就可以简单地忽略这个问题。

     

                                                                                       本文内容摘自《TCP/IP详解 卷1:协议(中文版)第2版》,有改动

           

    展开全文
  • tcp/ip 上,丢包重传机制

    千次阅读 2016-10-10 15:08:15
    TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。 注意,接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4...

    废话少说,首先,我们需要知道TCP在网络OSI的七层模型中的第四层——Transport层,IP在第三层——Network层,ARP在第二层——Data Link层,在第二层上的数据,我们叫Frame,在第三层上的数据叫Packet,第四层的数据叫Segment。

    首先,我们需要知道,我们程序的数据首先会打到TCP的Segment中,然后TCP的Segment会打到IP的Packet中,然后再打到以太网Ethernet的Frame中,传到对端后,各个层解析自己的协议,然后把数据交给更高层的协议处理。

    TCP头格式

    接下来,我们来看一下TCP头的格式

    TCP头格式(图片来源

    你需要注意这么几点:

    • TCP的包是没有IP地址的,那是IP层上的事。但是有源端口和目标端口。
    • 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, dst_port)准确说是五元组,还有一个是协议。但因为这里只是说TCP协议,所以,这里我只说四元组。
    • 注意上图中的四个非常重要的东西:
      • Sequence Number是包的序号,用来解决网络包乱序(reordering)问题。
      • Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题
      • Window又叫Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的
      • TCP Flag ,也就是包的类型,主要是用于操控TCP的状态机的

    关于其它的东西,可以参看下面的图示

    图片来源

    TCP的状态机

    其实,网络上的传输是没有连接的,包括TCP也是一样的。而TCP所谓的“连接”,其实只不过是在通讯的双方维护一个“连接状态”,让它看上去好像有连接一样。所以,TCP的状态变换是非常重要的。

    下面是:“TCP协议的状态机”(图片来源) 和 “TCP建链接”、“TCP断链接”、“传数据” 的对照图,我把两个图并排放在一起,这样方便在你对照着看。另外,下面这两个图非常非常的重要,你一定要记牢。(吐个槽:看到这样复杂的状态机,就知道这个协议有多复杂,复杂的东西总是有很多坑爹的事情,所以TCP协议其实也挺坑爹的)

     

    很多人会问,为什么建链接要3次握手,断链接需要4次挥手?

    • 对于建链接的3次握手,主要是要初始化Sequence Number 的初始值。通信的双方要互相通知对方自己的初始化的Sequence Number(缩写为ISN:Inital Sequence Number)——所以叫SYN,全称Synchronize Sequence Numbers。也就上图中的 x 和 y。这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输的问题而乱序(TCP会用这个序号来拼接数据)。
    • 对于4次挥手,其实你仔细看是2次,因为TCP是全双工的,所以,发送方和接收方都需要Fin和Ack。只不过,有一方是被动的,所以看上去就成了所谓的4次挥手。如果两边同时断连接,那就会就进入到CLOSING状态,然后到达TIME_WAIT状态。下图是双方同时断连接的示意图(你同样可以对照着TCP状态机看):


    两端同时断连接(图片来源

     

    另外,有几个事情需要注意一下:

    • 关于建连接时SYN超时。试想一下,如果server端接到了clien发的SYN后回了SYN-ACK后client掉线了,server端没有收到client回来的ACK,那么,这个连接处于一个中间状态,即没成功,也没失败。于是,server端如果在一定时间内没有收到的TCP会重发SYN-ACK。在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻售,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才会把断开这个连接。
    • 关于SYN Flood攻击。一些恶意的人就为此制造了SYN Flood攻击——给服务器发了一个SYN后,就下线了,于是服务器需要默认等63s才会断开连接,这样,攻击者就可以把服务器的syn连接的队列耗尽,让正常的连接请求不能处理。于是,Linux下给了一个叫tcp_syncookies的参数来应对这个事——当SYN队列满了后,TCP会通过源地址端口、目标地址端口和时间戳打造出一个特别的Sequence Number发回去(又叫cookie),如果是攻击者则不会有响应,如果是正常连接,则会把这个 SYN Cookie发回来,然后服务端可以通过cookie建连接(即使你不在SYN队列中)。请注意,请先千万别用tcp_syncookies来处理正常的大负载的连接的情况。因为,synccookies是妥协版的TCP协议,并不严谨。对于正常的请求,你应该调整三个TCP参数可供你选择,第一个是:tcp_synack_retries 可以用他来减少重试次数;第二个是:tcp_max_syn_backlog,可以增大SYN连接数;第三个是:tcp_abort_on_overflow 处理不过来干脆就直接拒绝连接了。
    • 关于ISN的初始化。ISN是不能hard code的,不然会出问题的——比如:如果连接建好后始终用1来做ISN,如果client发了30个segment过去,但是网络断了,于是 client重连,又用了1做ISN,但是之前连接的那些包到了,于是就被当成了新连接的包,此时,client的Sequence Number 可能是3,而Server端认为client端的这个号是30了。全乱了。RFC793中说,ISN会和一个假的时钟绑在一起,这个时钟会在每4微秒对ISN做加一操作,直到超过2^32,又从0开始。这样,一个ISN的周期大约是4.55个小时。因为,我们假设我们的TCP Segment在网络上的存活时间不会超过Maximum Segment Lifetime(缩写为MSL – Wikipedia语条),所以,只要MSL的值小于4.55小时,那么,我们就不会重用到ISN。
    • 关于 MSL 和 TIME_WAIT。通过上面的ISN的描述,相信你也知道MSL是怎么来的了。我们注意到,在TCP的状态图中,从TIME_WAIT状态到CLOSED状态,有一个超时设置,这个超时设置是 2*MSL(RFC793定义了MSL为2分钟,Linux设置成了30s)为什么要这有TIME_WAIT?为什么不直接给转成CLOSED状态呢?主要有两个原因:1)TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到Ack,就会触发被动端重发Fin,一来一去正好2个MSL,2)有足够的时间让这个连接不会跟后面的连接混在一起(你要知道,有些自做主张的路由器会缓存IP数据包,如果连接被重用了,那么这些延迟收到的包就有可能会跟新连接混在一起)。你可以看看这篇文章《TIME_WAIT and its design implications for protocols and scalable client server systems
    • 关于TIME_WAIT数量太多。从上面的描述我们可以知道,TIME_WAIT是个很重要的状态,但是如果在大并发的短链接下,TIME_WAIT 就会太多,这也会消耗很多系统资源。只要搜一下,你就会发现,十有八九的处理方式都是教你设置两个参数,一个叫tcp_tw_reuse,另一个叫tcp_tw_recycle的参数,这两个参数默认值都是被关闭的,后者recyle比前者resue更为激进,resue要温柔一些。另外,如果使用tcp_tw_reuse,必需设置tcp_timestamps=1,否则无效。这里,你一定要注意,打开这两个参数会有比较大的坑——可能会让TCP连接出一些诡异的问题(因为如上述一样,如果不等待超时重用连接的话,新的连接可能会建不上。正如官方文档上说的一样“It should not be changed without advice/request of technical experts”)。
      • 关于tcp_tw_reuse。官方文档上说tcp_tw_reuse 加上tcp_timestamps(又叫PAWS, for Protection Against Wrapped Sequence Numbers)可以保证协议的角度上的安全,但是你需要tcp_timestamps在两边都被打开(你可以读一下tcp_twsk_unique的源码 )。我个人估计还是有一些场景会有问题。
      • 关于tcp_tw_recycle。如果是tcp_tw_recycle被打开了话,会假设对端开启了tcp_timestamps,然后会去比较时间戳,如果时间戳变大了,就可以重用。但是,如果对端是一个NAT网络的话(如:一个公司只用一个IP出公网)或是对端的IP被另一台重用了,这个事就复杂了。建链接的SYN可能就被直接丢掉了(你可能会看到connection time out的错误)(如果你想观摩一下Linux的内核代码,请参看源码 tcp_timewait_state_process)。
      • 关于tcp_max_tw_buckets。这个是控制并发的TIME_WAIT的数量,默认值是180000,如果超限,那么,系统会把多的给destory掉,然后在日志里打一个警告(如:time wait bucket table overflow),官网文档说这个参数是用来对抗DDoS攻击的。也说的默认值180000并不小。这个还是需要根据实际情况考虑。

    Again,使用tcp_tw_reuse和tcp_tw_recycle来解决TIME_WAIT的问题是非常非常危险的,因为这两个参数违反了TCP协议(RFC 1122) 

    其实,TIME_WAIT表示的是你主动断连接,所以,这就是所谓的“不作死不会死”。试想,如果让对端断连接,那么这个破问题就是对方的了,呵呵。另外,如果你的服务器是于HTTP服务器,那么设置一个HTTP的KeepAlive有多重要(浏览器会重用一个TCP连接来处理多个HTTP请求),然后让客户端去断链接(你要小心,浏览器可能会非常贪婪,他们不到万不得已不会主动断连接)。

    数据传输中的Sequence Number

    下图是我从Wireshark中截了个我在访问coolshell.cn时的有数据传输的图给你看一下,SeqNum是怎么变的。(使用Wireshark菜单中的Statistics ->Flow Graph… )

    你可以看到,SeqNum的增加是和传输的字节数相关的。上图中,三次握手后,来了两个Len:1440的包,而第二个包的SeqNum就成了1441。然后第一个ACK回的是1441,表示第一个1440收到了。

    注意:如果你用Wireshark抓包程序看3次握手,你会发现SeqNum总是为0,不是这样的,Wireshark为了显示更友好,使用了Relative SeqNum——相对序号,你只要在右键菜单中的protocol preference 中取消掉就可以看到“Absolute SeqNum”了

    TCP重传机制

    TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。

    注意,接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?我们要知道,因为正如前面所说的,SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。

    超时重传机制

    一种是不回ack,死等3,当发送方发现收不到3的ack超时后,会重传3。一旦接收方收到3后,会ack 回 4——意味着3和4都收到了。

    但是,这种方式会有比较严重的问题,那就是因为要死等3,所以会导致4和5即便已经收到了,而发送方也完全不知道发生了什么事,因为没有收到Ack,所以,发送方可能会悲观地认为也丢了,所以有可能也会导致4和5的重传。

    对此有两种选择:

    • 一种是仅重传timeout的包。也就是第3份数据。
    • 另一种是重传timeout后所有的数据,也就是第3,4,5这三份数据。

    这两种方式有好也有不好。第一种会节省带宽,但是慢,第二种会快一点,但是会浪费带宽,也可能会有无用功。但总体来说都不好。因为都在等timeout,timeout可能会很长(在下篇会说TCP是怎么动态地计算出timeout的)

    快速重传机制

    于是,TCP引入了一种叫Fast Retransmit 的算法不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。

    比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。示意图如下:

    Fast Retransmit只解决了一个问题,就是timeout的问题,它依然面临一个艰难的选择,就是重转之前的一个还是重装所有的问题。对于上面的示例来说,是重传#2呢还是重传#2,#3,#4,#5呢?因为发送端并不清楚这连续的3个ack(2)是谁传回来的?也许发送端发了20份数据,是#6,#10,#20传来的呢。这样,发送端很有可能要重传从2到20的这堆数据(这就是某些TCP的实际的实现)。可见,这是一把双刃剑。

    SACK 方法

    另外一种更好的方式叫:Selective Acknowledgment (SACK)(参看RFC 2018),这种方式需要在TCP头里加一个SACK的东西,ACK还是Fast Retransmit的ACK,SACK则是汇报收到的数据碎版。参看下图:

    这样,在发送端就可以根据回传的SACK来知道哪些数据到了,哪些没有到。于是就优化了Fast Retransmit的算法。当然,这个协议需要两边都支持。在 Linux下,可以通过tcp_sack参数打开这个功能(Linux 2.4后默认打开)。

    这里还需要注意一个问题——接收方Reneging,所谓Reneging的意思就是接收方有权把已经报给发送端SACK里的数据给丢了。这样干是不被鼓励的,因为这个事会把问题复杂化了,但是,接收方这么做可能会有些极端情况,比如要把内存给别的更重要的东西。所以,发送方也不能完全依赖SACK,还是要依赖ACK,并维护Time-Out,如果后续的ACK没有增长,那么还是要把SACK的东西重传,另外,接收端这边永远不能把SACK的包标记为Ack。

    注意:SACK会消费发送方的资源,试想,如果一个攻击者给数据发送方发一堆SACK的选项,这会导致发送方开始要重传甚至遍历已经发出的数据,这会消耗很多发送端的资源。详细的东西请参看《TCP SACK的性能权衡

    Duplicate SACK – 重复收到数据的问题

    Duplicate SACK又称D-SACK,其主要使用了SACK来告诉发送方有哪些数据被重复接收了RFC-2833 里有详细描述和示例。下面举几个例子(来源于RFC-2833

    D-SACK使用了SACK的第一个段来做标志,

    • 如果SACK的第一个段的范围被ACK所覆盖,那么就是D-SACK
    • 如果SACK的第一个段的范围被SACK的第二个段覆盖,那么就是D-SACK

    示例一:ACK丢包

    下面的示例中,丢了两个ACK,所以,发送端重传了第一个数据包(3000-3499),于是接收端发现重复收到,于是回了一个SACK=3000-3500,因为ACK都到了4000意味着收到了4000之前的所有数据,所以这个SACK就是D-SACK——旨在告诉发送端我收到了重复的数据,而且我们的发送端还知道,数据包没有丢,丢的是ACK包。

    	Transmitted  Received    ACK Sent
    	Segment      Segment     (Including SACK Blocks)
    
    	3000-3499    3000-3499   3500 (ACK dropped)
    	3500-3999    3500-3999   4000 (ACK dropped)
    	3000-3499    3000-3499   4000, SACK=3000-3500
                                            ---------

     示例二,网络延误

    下面的示例中,网络包(1000-1499)被网络给延误了,导致发送方没有收到ACK,而后面到达的三个包触发了“Fast Retransmit算法”,所以重传,但重传时,被延误的包又到了,所以,回了一个SACK=1000-1500,因为ACK已到了3000,所以,这个SACK是D-SACK——标识收到了重复的包。

    这个案例下,发送端知道之前因为“Fast Retransmit算法”触发的重传不是因为发出去的包丢了,也不是因为回应的ACK包丢了,而是因为网络延时了。

        Transmitted    Received    ACK Sent
        Segment        Segment     (Including SACK Blocks)
    
        500-999        500-999     1000
        1000-1499      (delayed)
        1500-1999      1500-1999   1000, SACK=1500-2000
        2000-2499      2000-2499   1000, SACK=1500-2500
        2500-2999      2500-2999   1000, SACK=1500-3000
        1000-1499      1000-1499   3000
                       1000-1499   3000, SACK=1000-1500
                                              ---------

     

    可见,引入了D-SACK,有这么几个好处:

    1)可以让发送方知道,是发出去的包丢了,还是回来的ACK包丢了。

    2)是不是自己的timeout太小了,导致重传。

    3)网络上出现了先发的包后到的情况(又称reordering)

    4)网络上是不是把我的数据包给复制了。

     知道这些东西可以很好得帮助TCP了解网络情况,从而可以更好的做网络上的流控

    Linux下的tcp_dsack参数用于开启这个功能(Linux 2.4后默认打开)

    展开全文
  • 提出了一种新型的基于反馈的网络编码(FNC)重传机制,利用seen机制中的隐含信息来获取接收方解码所需的重传分组个数,并改变了编码规则使部分分组可以提前解码。该机制不仅可以处理有固定误码率的随机分组丢失,还...
  • TCP协议重传机制

    2021-04-03 17:30:24
    TCP重传机制包括两部分:超时重传机制和快速重传机制。 在说超时重传和快速重传机制之前我们先说说TCP的传输确认机制: 假如要传输一个大小为1M的数据包,由于最大传输单元(MTU)的限制,需要将包拆分为N个小包进行...

    TCP协议是一种可靠的,面向连接的,基于字节流的传输协议。既然是一种可靠的传输协议,那么必须有一种机制来保证接收方收到的数据是完整地,今天聊聊TCP协议下的重传机制。

    TCP重传机制包括两部分:超时重传机制和快速重传机制

    背景:TCP的传输确认机制

    假如要传输一个大小为1M的数据包,由于最大传输单元(MTU)的限制,需要将包拆分为N个小包进行传输,并且对每一个包进行编号,这里假如这个N为200,那么编号就为1,2,3,4.....198,199,200

    发送方按照编号顺序Seq=1,2,3,4,5,....,200发送给接收方,接收方收到包后需要给接收方发送ACK=2,3,4,5,6....201的确认包,接收方将所有包接收完成之后则进行数据拼接,完成一次传输。由于网络环境的复杂性,这里会涉及到包乱序、重复、丢包问题

    乱序:发送方按照序号Seq=1,2,3,4,5的顺序发包,接收方收到的包可能是1,2,4,3,5

    解决方案:接收方发现先收到了序号为4的包,那么会将编号为4的包先缓存起来,等收到了编号为3的包后再将他们按顺序进行排列

    丢包:发送方按照序号Seq=1,2,3,4,5的顺序发包,接收方收到的包可能是1,2,3,5

    解决方案:接收方发现先收到了编号为5的包,但是编号为4的包迟迟没有收到,那么这里会触发重传机制,让接收方知道,编号为4的包丢掉了,需要重新发,这里的重传机制在下面细讲。

    重复包:由于包在网络层有延迟等触发TCP重传,接收方收到的包可能是1,2,3,3,4,5

    解决方案:接收方发现收到的编号为3的包已经存在了,那么在此收到编号为3的包,它也不会进行处理,直接丢弃。

    超时重传机制,即基于计时器的重传

    顾名思义,简单来讲,超时重传就是发送方设置一个超时时间,如果在这个时间内未收到接收方的ACK确认应答,那么发送方即对包进行重发。

    超时时间,我们一般超时时间设置的都比较简单,比如200ms,但是现实中网络环境比较复杂,快一点的传输耗时50ms,这种情况下用200ms来判断超时传输效率会有些低;假设你访问某国外网站,延迟有 130 ms,这就麻烦了,正常的数据包都可能被认为是超时,导致大量数据包被重发,可以想象,重发的数据包也很容易被误判为超时,所以设置固定值是很不可靠的,我们要根据网络延迟,动态调整超时时间,延迟越大,超时时间越长

    在这里先引入两个概念:

    • RTT(Round Trip Time):往返时延,也就是数据包从发出去到收到对应 ACK 的时间。RTT 是针对连接的,每一个连接都有各自独立的 RTT。
    • RTO(Retransmission Time Out):重传超时,也就是前面说的超时时间。

    这种机制下,每个数据包都有相应的计时器,一旦超过 RTO 而没有收到 ACK,就重发该数据包。没收到 ACK 的数据包都会存在重传缓冲区里,等到 ACK 后,就从缓冲区里删除。

    首先明确一点,对 TCP 来说,超时重传是相当重要的事件(RTO 往往大于两倍的 RTT,超时往往意味着拥塞),一旦发生这种情况,TCP 不仅会重传对应数据段,还会降低当前的数据发送速率,因为TCP 会认为当前网络发生了拥塞。

    快速重传机制:

    快速重传机制「RFC5681」基于接收端的反馈信息来引发重传,而非重传计时器超时。

    刚刚提到过,基于计时器的重传往往要等待很长时间,而快速重传使用了很巧妙的方法来解决这个问题:服务器如果收到乱序的包,也给客户端回复 ACK,只不过是重复的 ACK。就拿刚刚的例子来说,收到乱序的包 6,7,8,9 时,服务器全都发 ACK = 5。这样,客户端就知道 5 发生了空缺。一般来说,如果客户端连续三次收到重复的 ACK,就会重传对应包,而不需要等到计时器超时。

     

     

    注:以上文章参考:https://zhuanlan.zhihu.com/p/101702312,这里对重传机制有详细的图示描述。

          https://www.zhihu.com/question/280521822 这里对TCP的确认机制有简单,明了的描述。

    展开全文
  • TCP协议的确认重传机制

    千次阅读 2019-09-18 07:32:47
    TCP协议是面向连接的传输层协议,TCP的传输特点具有可靠性,它具有面向连接服务来确保可靠稳定传输,而确认重传机制是TCP协议保证可靠稳定传输最重要的机制,他包括累计确认、超时时间计算、快速重传等几个方面。...

    TCP协议是面向连接的传输层协议,TCP的传输特点具有可靠性,它具有面向连接服务来确保可靠稳定传输,而确认重传机制是TCP协议保证可靠稳定传输最重要的机制,他包括累计确认、超时时间计算、快速重传等几个方面。

    确认重传机制

    在发送一个数据之后,就开启一个定时器,若是在这个时间内没有收到发送数据的ACK确认报文,则对该报文进行重传,在达到一定次数还没有成功时放弃并发送一个复位信号。

    1、累计确认

    累计确认就是TCP协议的确认方法,TCP使用可变长度报文段来发送数据,重传时,报文段数据可能会比原报文段数据包含更多的数据,因此对数据报和报文段无法进行简单的确认。TCP使用流序号对流中的一个位置进行确认,即序号和确认号一一对应,接收方使用序号将报文段重新排序,且以正确接收到的流的最长连续前缀进行确认。

    TCP协议的确认重传机制

    2、超时时间计算

    超时时间计算是开启定时器的设定时间,从而保证网络资源利用率,避免因定时器的时间(RTO)不确定而影响网络传输效率。

    TCP协议的确认重传机制

    即发送方连续发送三个数据包,第二个数据包丢失,接收方未接收到,无法返回ACK。每当发送一个数据包时,就启动一个定时器, 而定时器溢出了,发送方还没接收到接收方返回的ACK时,确定重传。

    3、快速重传

    快速重传机制是发送方在接收端的反馈信息后引发重传,而不是定时器超时重传。快速重传机制要求当接收到失序报文段时,TCP需要立即生成确认信息(重复ACK),并且失序情况表明在后续数据到达前出现了丢包,发送端的工作即为尽快填补丢包带来的数据段空缺。

    展开全文
  • 小白:你知道吗?数据在传输的时候是分割成一小块一小块传输的,我们把这一小块的数据称之为一个分组。我们在传输这块分组的时候,主要面临两个问题。...接下来我们先来谈谈第一种情况吧,即分组...
  • 5G/NR 学习笔记: 重传机制

    千次阅读 2019-06-27 07:11:35
    LTE中的重传机制是两层的:MAC层和RLC层 两层重传机制,是为了在速度与可靠度之间找到权衡。 HARQ目标是快速,负责传输信道/每个CC,对象是TB,错误率在1%左右 RLC目标是可靠性,负责逻辑信道,错误率为10e-5 一...
  • 一、引言 某天早晨,还没起床,就听到群里有人喊sentry报大量1001超时,反馈具体在A机器上,...二、TCP机制 在TCP三次握手的过程中,当客户端发送SYN分节之后,如果没有收到服务端返回的确认ACK,那么TCP会在...
  • 1 重传机制 超时重传   ①在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据,也就是我们常说的超时重传。   ②超时重传时间 RTO(Retransmission Timeout ...
  • 自动重传请求 ARQ-Automatic Repeat RequestARQ的起源ARQ的核心思想SRT对ARQ机制的改进 ARQ的起源 ARQ(Automatic Repeat-Request)即自动重传请求技术是差错控制技术中的一种,最早也许可以追溯到其在X.25系统的...
  • 于是我就想起了在计算机网络中讲数据链路层协议时的“选择重传ARQ”协议(见《计算机网络》第四版 AndrewS.Tanenbaum的p187)来解决丢包问题。我不是一个好学生,所以具体细节忘了一些,遂找出那本书,把那一小节...
  • TCP重传

    千次阅读 2019-06-10 15:50:40
    一、TCP重传 1、重传的原因 1)发端计时器超时 TCP每发送一个报文段,就对这个报文段设置一次计时器。当计时器超时而没有收到确认时,就重传该报文。 注:原来报文哪去了呢?两种可能: 1)在中间节点丢了。2)...
  • 上一次我们知道了TCP协议通过连接管理机制保证可靠性,今天我们继续来看一看TCP协议中其他几种保证可靠性的方法。 确认应答机制 在将这部分的内容之前我们应该首先知道的一点就是,在TCP中,TCP将每个字节的数据都...
  • 信道编码之混合自动重传请求HARQ1、概念介绍1.1、自动重传请求协议(ARQ)1.1.1、停等式(stop-and-wait protocol )1.1.2、后退N 步式1.1.3、选择重发式1.2、相关概念1.2.1、HARQ process number1.2.2、NDI1.2.3、...
  • 自动重传请求协议 ARQ

    2021-08-22 16:15:43
    传统的自动重传请求分为三种:停止-等待 ARQ(stop and wait)、回退N帧 ARQ(go-back-n)、选择重传 ARQ(selective repeat)。 优点:比较简单 。因而被广泛的应用在分组交换网络中。 缺点:通信信道的利用率不高,即...
  • 重传阶段根据反馈机制结果采取随机接入方式优先对有机会编码的丢失信息包进行组合,然后通过牺牲之前重传过程中传输失败的节点为信息提供空间分集增益,从而减少重传次数。最后在不同信道环境下,该策略与未协作...
  • HARQ重传的概述

    2017-12-12 21:18:00
    HARQ(hybrid automatic ... 重传机制有三种: =停止等待 是指协议每发送一帧数据后,等待对方的反应ack、nack 回退 : 是指不停地发送数据,无需等待对方的反馈,直到接收方反馈错误NACK,发送方就重发错误数据...
  • 我们都知道 TCP 协议具有重传机制,也就是说,如果发送方认为发生了丢包现象,就重发这些数据包。很显然,我们需要一个方法来「猜测」是否发生了丢包。最简单的想法就是,接收方每收到一个包,就向发送方返回一个 ...
  • 邻端口的调度结果并以此对目标端口所反馈的缓存信息进行修正,基于修正后的信息进行算法调度使得.FRTM-TSA 能够避免信元冲突和信元失序,也无需在输出端口设置排序缓存。理论分析和仿真结果均表明.FRTM-TSA 能够以...
  • 快速重传机制基于接收端的反馈信息来引发重传,而非重传计时器的超时。 因此与超时重传相比,快速重传能更加及时有效地修复丢包情况。典型的TCP同时实现了两者 重复ACK 在详细讨论快速重传前,首先需要了解当接收...
  • tcp_keepalive_intvl (integer; default: 75; since Linux 2.4) The number of ...我记得滑动窗口的机制是发送一批报文出去,等待连续的反馈。当然这俩包稍微有点大(每个大概1.3k); : ...................
  • 确认应答机制 超时重传机制 滑动窗口机制 拥塞控制机制 慢启动 拥塞避免 快重传 快恢复 延时应答机制和捎带应答机制
  • 对超时重传、滑动窗口、拥塞控制的简单认识 我们之前说过TCP对于数据的可靠传输可以做到: 数据准确的到达对端 数据到达后是有序的 ...TCP重传机制 TCP滑动窗口 TCP的拥塞控制 接下来,我们对其依次进...
  • TCP超时与重传

    2021-10-07 23:03:05
    TCP拥有两套独立机制来完成重传,一是基于时间,二是基于确认信息的构成。第二种方法通常比第一种更高效。 对于基于时间的重传:TCP在发送数据时会设置一个计时器,若至计时器超时仍未收到数据确认信息,则会引发...
  • RabbitMq手动确认时的机制

    千次阅读 热门讨论 2019-05-15 17:34:27
    因为抛出异常就算是试也非常有可能会继续出现异常,当试次数完了之后消息就只有重启应用才能接收到了,很有可能导致消息消费不及时。当然可以配置RepublishMessageRecoverer来解决,但是万一...
  • TCP通过确认应答和超时重传可以保证数据可靠传输 使用滑动窗口完成流量控制和拥塞控制 使用延迟应答来保证滑动窗口足够大 ...超时重传机制 当主机A向主机B发送的数据发生丢包,无法到达主机B时,...
  • 重传,而 nack机制就是用来处理重传逻辑的,需要注意一点由于udp本身是无序的,所以在进行丢包重传时要做一定的特殊处理。 二、nack 报文介绍 文档 :RFC4585 其中PT=205,FMT=1 ,Packet identifier即为丢失的...
  • TCP-超时与重传

    千次阅读 2018-09-01 16:03:12
    主要内容: 超时与重传简单实例 设置超时重传方法 基于计时器重传 快速重传 带选择确认的重传 伪超时与重传 包失序与包重复 目的度量 重新组包 与TCP重传相关的攻击 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,940
精华内容 7,576
关键字:

反馈重传机制