RTT和RTO
RTT(Round-Trip Time)往返时延:发送一个数据包到收到对应的ACK,所花费的时间。
简单来说就是我发送一个数据包,然后对端回发一个ACK,当接我收到ACK之后,就能计算出从我发出包到接到回应过了多久,这个时间就是RTT。RTT计算就是一个时间差
RTO(Rnsmission time-out)重传间隔:重传时间间隔
TCP在发送一个数据包之后,会启动一个重传定时器,而RTO就是这个定时器的重传时间
比如我一开始定义一个定时时间,如果你回复了ACK,重传定时器就会自动失效,就不用重传。如果没有回复给我ACK,并且RTO定时器时间又到了,我就重传。
TCP会将数据拆分成段进行发送,处于效率和传输速度的考虑,不可能一段段来发送的,等到上一段数据被确认之后,再发送一下段数据,这个效率是非常低的。为了实现TCP的批量发送,TCP必须解决可靠传输,以及包乱序的问题。所以TCP需要知道网络实际处理的带宽,或是数据处理速度。这样才不会引起网络拥塞,导致丢包。
TCP使用滑动窗口做流量控制与乱序重排
TCP滑动窗口的两个作用
保证TCP的可靠性
保证TCP的流控特性
TCP报文头有一个字段是Window。用于接收方通知发送方自己还有多少缓冲区可以接收数据,发送方根据接收方的处理能力来发送数据,不会导致接收方处理不过来。这便是流量控制。
滑动窗口的机制还体现出了面向字节流的设计思路
窗口数据的计算过程
左图是TCP协议的发送端缓冲区 右图是接收端缓冲区 左边往右边发数据
下面的长方形代表要发送的数据流,假设里面装满了数据,并且需要按照顺序,从左向右发送,或者接收。
发送方
LastByteAcked指向收到的连续最大的ACK的位置,也就是从左端算起,连续已经被接收端的程序发送ACK回值确认,已收到的sequence number。
LastByteSent指向已发送的最后一个字节的位置,该位置只是发出去了,但是还没有收到ACK的回应。
LastByteWritten指向上层应用已写完最后一个字节的位置,即当前程序已经准备好的,需要发送的最新的一个数据段。
浅蓝色区域代表发送出去,但是还是没有收到确认的
浅蓝色区域前面的白色区域代表发送出去并且已经收到接收端确认了的
由图可以看出从 LastByteAcked 到 LastByteWritten 都是没有出现间隔的,都是连续的。
接收方
LastByteRead 指向上层应用以及读完的最后一个字节的位置,也就是说收到了发送方的位置,并且已经处理已经回值了的数据的最后一个位置。
NextByteExpected 指向收到的连续最大的 sequence 的位置。
LastByteRead 到 NextByteExpected 表示已经收到了,但是还是没有发送给发送方回值的
LastByteRcvd 指向已收到的最后一个字节的位置。
由图可以看出 NextByteExpected 到 LastByteRcvd 空白区域 表示 有一些 sequence 还没有到达。
此时我们可以根据图中的数值,计算出接收方的window的大小,并且回发给发送方,让其计算出发送方的剩余可以发送的数据大小。
AdvertisedWindow 接收方还能处理的数据的量 MaxRcvBuffer 接收方能接收数据的最大数据量也可以理解为 接收端缓存时的大小 (LastByteRcvd - LastByteRead) 表示当前接收方未接收的数据 或者 还没有到的预定的数据 留出来的空间
用最大的缓存减去已经占据的缓存 就得出 还能够接收的数据量 进而就可以把 AdvertisedWindow 告知发送方
AdvertisedWindow = MaxRcvBuffer - (LastByteRcvd - LastByteRead)
而发送方根据AdvertisedWindow的值就需要保证 LastByteSent 减去 LastByteAcked 要小于或者等于 AdvertisedWindow的值
即已发送且带确认的数据量要小于 接收方的window大小
EffectiveWindow = AdvertisedWindow - (LastByteSent - LastByteAcked)
窗口内剩余可发送的数据大小 EffectiveWindow (LastByteSent - LastByteAcked) 待确认的数据量
TCP会话的发送方
对于TCP会话的发送方 任何时候在其发送缓存类的数据都可以分为4类
Category #1 :已经发送并且得到端的回应
Category #2:已经发送但没得到端的回应
Category #3:未发送但对端允许发送的
Category #4:未发送但由于达到了window的大小对端不允许发送的数据
Category #2:已经发送但没得到端的回应 ,Category #3:未发送但对端允许发送的 这两部分数据所组成的连续空间就称为发送窗口
当收到接收方收到新的ACK对于发送窗口中后续字节的确认时,窗口就会进行滑动。
假设原滑动窗口,已发送但是未被确认的序号是32到40,此时如果32和33都没有被确认。而34被确认原滑动窗口不会向右边滑动。只有等到32-34被确认之后,即连续被确认之后滑动窗口才会被移动。原滑动窗口没有被移动之前,序号大于等于52的数据,即窗口外的数据是不能被发送的。
此时假设32-35都被确认了,则滑动窗口会向右滑动4位,到36这个位置。进而程序就能发送52-55的数据。
在某一时刻,在接收缓存内会存在三种状态
第一种状态是:已接收并且已发送回值的状态
第二种状态是:未接收但是可以接收 准备接收的状态
第三种状态是:未接收并且不能接收 达到窗口的阈值
由于ACK直接由TCP栈回复,默认没有应用延迟,不存在已接收未回复ACK的状态
其中未接收并且准备接收的空间 称为 接收窗口。
TCP最基本的传输可靠性来源于确认重传机制,TCP滑动窗口的可靠性也是建立确认重传基础上的。
发送窗口只有收到接收端对于本段发送窗口内发送字节ACK确认,才会移动发送窗口的左边界。
接收端口只有在前面所有的段都确认的情况下,才会移动左边界,当在前面还是字节未接收但收到后面字节的情况下,窗口是不会移动的,并不对后续字节确认,以此确认对端,对这些数据进行重传。
滑动窗口的大小可以依据一定策略动态调整,应用会根据自身处理能力的变化,通过本端TCP接收窗口大小的控制来实现流量限制