网络协议 TCP 数字编号和重发

网络协议 TCP 数字编号和重发


TCP 作为一种可靠的传输协议,在他的背后注定会有一套数据包的安全检查与重发确认,那么如何检查一包数据是否正确的被对方接收,这就需要为每个数据包,做标签,即数据编号,当发现数据包,丢失或者超时就会发起重传机制

1. TCP 的数字编号

作为一种确认机制的根本,编号起到了非常重要的作用。
TCP 数据端以字节为单位对数据段中的“数据”部分进行一一编号,确保每个字节的数据都可以有序传送和接收。

在前边我们介绍了tcp的数据包结构,并且介绍了序号和确认号,序号就是这里所说的数字编号,在数据包头中序号占32位,在tcp发起连接时起始序号是一个随机数,数据端头中的序号是这包数据的第一个字节的编号,假设起始数据数是 100(这里不考虑tcp 握手过程中消耗的编号),发送的数据包长度为100,那么该包的第一个数据字节的编号是101,那么序号就是101,那么最后一个字节的序号就是200.,假如对方成功收到数据,会收到对方的确认包(这里用到了数据段的确认机制,简单讲就是对方收到数据包后,要发送给数据的发送端一包确认数据,告诉发送方,你的数据包我收到了,确认号ack=发送方seq序号+ 数据包长度 即 201) 那么此时收到的的确认号就是201,那么发送下一包数据的序号就是201,而不是101.这就是tcp数字编号的的基本原理,后续的重传,超时重传,粘包,分包,都是依赖它来做操作的。

2. TCP 确认机制的特点

我们将数据包中每个字节进行编号,seq每包的序号就是该包第一个字节的序号,发送一包收据后会收到对方发送回来的ack 确认数据包这就是数据包的确认。

2.1 TCP一次可发送多个数据包

在实际中TCP可以不等接收到对方发送的确认数据段,就可一次连续性的发送多个数据端,这样可大大提高发送的效率,但是一次发送的多少数据段时受到对方返回窗口大小字段值和当前可用发送窗口大小双重限制的,因为发送端还要对没有收到确认的数据包进行缓存,这也会占用窗口大小。假设发送端和接收端窗口大小为2000字节,一包数据假设为100字节,那么,发送端可以一次性连续向发送端发送20包数据,假如这时有两包数据没有收到确认,且接受端返回的窗口大小为2000,那么现在发送端只能发送18包1800字节数据,因为还有两包没有收到确认,占用了200字节的窗口大小。
假设现在现在接收端返回的窗口大小为1000,发送端也收到了所有发送出去数据的确认包,那么发送端窗口大小为2000,这时只能发送1000字节十包数据到接收端,因为对端只有1000字节的窗口大小接收,所以说发送数据包数,是受到两端窗口大小的限制的。

2.2 仅对连续接收的数据段进行确认

返回的确认数据段中的“确认号”字段置仅代表对端已正确接收的连续数据段,(最高字节序号+ 1),而不一定是已正确接收数据段中的“最高序号+ 1”,假如发送端发送了4包数据,每包100字节,序号为1,101,201,301,接收端收到了1,101,301,这三包数据,发送段收到的对应的ack为101,201,201,这时因为ack 只能是已正确接收的连续数据段最高序号+1,因为实际201 的数据包没有收到,那么301 返回的只能是101 这包的最高序号200 +1,所以说是201,即使301这包数据发送成功返回的依然是201。

2.3 不连续的数据将先缓存

当主机收到的数据段序号不连续时,不连续的数据部分不会向应用层提交,而是先缓存在“接收窗口”中,等到接收到中断的序号的数据包一起提交,这时尽管接收端已经正确接收到某些数据,仍不能向应用层提交,需要占用接收窗口空间,对于没有按照正确先后次序接收的数据,在向应用层提交时会重新按数据段进行组合,然后提交给应用层。
假设一包数据是100,接收端先后收到发送端发来的数据序号为1,101,201,301,601,401,801,501八包数据,那么接收段会将连续接收的前四包提交到应用层(1,101,201,301),并向发送端发送一个ack=401 的数据确认包,从接收窗口中将四包数据移除,并释放占用窗口空间,ack=401表示希望下次接收到数据的序号是401,即使接收端已经存在401的这包数据,因为它不是连续接收的最大数据段最高字节+1=501,现在的最高字节是401,现在接收端窗口中存在601,401,801,501,四包缓存数据,当接收端收到序号为501 的数据时(这里发送端重发了401 和 501),会将401,501,601,三包发送给应用层去除缓存中重复数据,释放窗口缓存300,这时接收窗口缓存数据包中还有801,因为701还未收到。

3. TCP 的重传机制

TCP 的重传有很多种情况,如超时重传,选择性确认也可叫快速重传。

1. 超时重传

超时重传是tcp保证数据可靠性的一个重要机制,其原理是在发送一个数据段以后就开启一个定时器(RTT),如果在这个定时器时间内没有收到来自对方的某个数据端的确认,发送端启动重传机制,重新发送对应的数据段,直到发送成功为止(这里接收端有足够缓冲区,发送端也有足够的缓存区),但是不是RTT定时器一到就会立即重传数据,毕竟从发送窗口缓存中找到对应的数据段,然后安排重新发送是需要时间的,实际上超时重发时间间隔大于RTT值也就是使用了RTO作为超时时间重发数据。
这里有几个词的概念RTT(消息发送的往返时间),SRTT(平滑的往返时间),RTO(超时时间),实际我们用的是计算后的RTO

1. RTT

RTT(Round Trip Time)消息发送的往返时间,由三部分组成:链路的传播时间(propagation delay)、末端系统的处理时间、路由器缓存中的排队和处理时间(queuing delay),其中,前两个部分的值对于一个TCP连接相对固定,路由器缓存中的排队和处理时间会随着整个网络拥塞程度的变化而变化。所以RTT的变化在一定程度上反应了网络的拥塞程度,RTO有下限,最小必须是200ms,也就是说即使网络状态再好 做小超时时间只能是200ms ,RTO最小值是内核编译是决定的,socket程序中无法修改,Linux TCP也没有任何参数可以改变这个值。.

2. SRTT

先根据RTT计算出SRTT(Smoothed Round Trip Time),然后根据一个最大、最小超时时间确定当前RTO。说明:srtt可以理解为“平滑化”的RTT,即在保持计算简单的情况尽量考虑历史RTT.

3.SRTT 的计算

这里涉及到,两个重要的问题,如何确定RTT的值,和RTO 超时时间,RTT 是一个数据段往返发送端和接收端时间的总和,在这中间可能经过多个性能不一样的网络,而且不同时刻网络的拥塞程度可能不一样,这就造成不同数据端RTT的时间并不一样,甚至波动非常大,但是TCP 必须适应这种波动,必须能动态的跟踪这些变化,相应的改变重传超时时间RTO 。
正因为RTT不是一个固定的值,所以出现了平滑RTT (SRTT):
SRTT(新的SRTT) =αSRTT( 旧的SRTT值) + (1-α)RTT (新的RTT样本值) ,SRTT的初始值就是第一个RTT值,这里的α 是一个平滑因子它决定了SRTT值的所占的权重 ,0 < =α < 1 ,RTC2988推荐a的典型值为0.125,如果α的值接近0,则表示新的SRTT 值与旧的SRTT值非常的接近,变化不大,相反,则变化比较大,显然,用这种方法计算出的各个时刻的SRTT 的值更加的平滑,更加的接近网络环境,假设两包数据的RTT都是2秒那么SRTT = 2 + 0.875*2=3.70秒。
SRTT = αSRTT + (1-α)RTT

4. RTO的计算

上边了解RTT和SRTT,实际上决定了RTO的值,那RTO如何计算,实际是比较难的,因为到底是RTT定时器到后就重传还是要等多长时间才重传,正常TCP βSRTT作为重传时间,起始超时时间设为2倍的SRTT 2SRTT β=2,(β>1) ,但是采用常数的β 值不够灵活按照上边的假设那么 RTO = 2 * SRTT = 7.4秒。后来在1988 年 Jacobson提出使用平均偏差作为标准偏差,就是(β SRTT)的新估算方法。要求维护另一个被平滑的偏差RTTD,
RTTD= αRTT(旧的RTT)+ (1-α) * (SRTT - RTT) 这里 α 可能与计算SRTT 时 的值相同,也可能不同,通常取0.25,现在大多数TCP都是用这个算法.假设两次都是RTT 都是2秒,
RTO = SRTT + 4 RTTD = 3.7 + 0.75 * 1.7=4.975
通过比较发现得到的RTO值从7.4 变为4.975明显平滑了许多。
这里可能需要注意的是,得到的是一个超时时间,就是说,只有在发送一包数据,我们会通过公式计算出一个RTO超时时间,这时关键参数是上一包数据的RTT 往返用时,起始时SRTT = RTT,假设这包没收到按照上边假设
RTO= SRTT(3.7 + 0.8752) + 4RTTD(4 (2+0.751.7))=5.5+ 42.3=15(大概) 也就是是说大概超时时间是15秒。
(*这里个人感觉还是比较合理的,如果哪位对这里的公式计算有更好的理解欢迎留言交流)
所以如果一直发送不成功,重发时间是指数及的增长的,这样有利与节省资源,这里再梳理下:重传机制就是发送一包数时,根据之前发送的来回时间或者首次超时默认时间,指定一个超时的时间,当数据包在指定超时时RTO间内没有收到对方的确认消息,这时启动超时重传,RTO将根据上次的SRTT RTT进行计算,得到这包的超时时间,当数据包发出后启动超时定时器,这时的超时时间相比上次的超时时间会有一个大的增加,根据公式 RTO = SRTT + 4 RTTD 得到,基本是指数及的增加,能更好的节省资源,同时又可以根据网络的变换,不停的调整RTO的值。

2. 快速重传 αβδεζθλμν

快速重传或者叫TCP 的选择性确认机制,他的本质是,tcp一次发送了N包数据(滑窗内一次发送的最大数据条数N,后边会讲),这时其中一包没有收到确认回复,当后续数据包被接收到,在收到的确认数据包中将会在TCP的扩展选项中携带已收到数据包的起始序号和结束序号,如果你对数据包头不了解可以查看TCP数据段 帧,同时ack 返回的是未收到的那包数据的起始编号,当发送端收到这包数据后通过ACK 可扩展字段,能够快速定位是那包数据没有发送成功,从而快速的重新发送这包数据。

1.选择性确认SACK

根据上边超时重传的特性我们知道,一包数据在超时时间内没有收到确认就会发起重传,但是有可能只是数据包中间的一包丢失也可能导致,发送端将该包及其以后的数据包又重新发送了以便,这显然没有必要,因为后续的包有可能已经存在了,比如接收端收到1,101,201,401,501,这时301数据包超时重发,紧接着401,501也触发了超时重传,401,501被重传,这显然没有这个必要,所以就有了选择性确认机制。
要实现选择性确认,必须在TCP传输链接时的SYN 数据段中包含“SACK-Permit”字段选项,表示在数据段中需要包含SACK字段,在这个字字段中包含接收端已经接收的不连续数据的所有起始字节号和结束字节号,且仅在ACK==1 时有效,这样发送端在收到后就知道是那一包数据接收端还没有收到,单独发送就可以了,从而避免了重复发送的问题。
这里需要注意的是,选项最大字节为40。SACK-Permit 中有有两个字段
Kind 占8位和Length占8位,但每个会占一个选项32位4字节,所已剩下32字节,最大仅能支持4个不连续数据段。

上一篇:视屏面试传输协议到底是TCP还是UDP


下一篇:计算机网络期末复习第一章