这里是Themberfue
上节我们讲完了TCP协议中保证其可靠性的最重要的三个机制,这节我们将深入更多保证TCP协议可靠性的机制。
滑动窗口
- 学过算法的小伙伴应该对滑动窗口这个不陌生,没错,滑动窗口这个算法就是出自TCP协议的机制的。没听过也没事,且听我一一道来。
- 通过前面的章节我们知道,TCP保证可靠性传输的一个是确认应答,也就是发送方发送一个报文,接收方收到后会发送给发送方一个确认报文ACK确认其收到了这个报文。但是,发送方发送报文后,不能立即发送下一段,还得先等待接收方对应的确认报文ACK,这样的传输效率是非常慢的,通常表现为包的往返时间越长通信性能就越低 ,为了解决这一问题,便引入了滑动窗口。
✨**滑动窗口(Sliding Window)**是TCP协议中的一种流量控制机制,用于高效管理数据的发送和接收,确保接收方不会因数据过多而被压垮,同时提升网络传输效率。
✨窗口: 发送窗口 :发送方维护的窗口,用于限制可以发送但未被确认的数据量。接收窗口 :接收方维护的窗口,用于告诉发送方它当前可以接收的数据量大小。**滑动:**窗口的起始和结束位置随着数据的发送、接收和确认不断滑动,动态调整未确认数据和可以发送的数据范围。
我不再一个一个传输了,我直接批量传输,将多份数据包直接传输给接收方,等发送到一定量后我再等待一下接收ACK报文,相当于用一份数据包的等待时间换了多组ACK的接收时间。但这样做依然有问题,就是我发送了多份数据包后等待,依然需要等待全部ACK接收后才可继续发送下多份。
解决办法就是我收到一份ACK后就直接继续发送下多份数据包。假设我一次性发送4份数据包,也就是(1-4000),我接受了1001ACK报文后就继续发送4001-8000的数据包就好,但实际并非这样,因为我可能我发送1-100后立刻就受到了1001ACK报文,还没发送1001-2000报文呢;这样没事,根据前面可知此时窗口的大小为4,我收到1001ACK报文后就让窗口向后移动一格就好了,此时窗口就变成了1001-5000。
- 通过图解我们可以清晰的看出来窗口大小的变化。此时你或许又会有疑问了:万一我1001的ACK报文还没收到,2001的ACK的报文就已经收到了,这种情况该怎么处理?很简单,前面我们提到每个数据包都有一个序号,这就体现到序号的好处了,既然你已经收到了2001ACK报文,那么你1001ACK报文就肯定已经收到了,不然你怎么可能给我2001的ACK报文。若先收到2001ACK报文,直接让窗口向后移动两格即可。
- 理论上,窗口越大,批量发的数据就越多,那么我效率就越高,实则不然,窗口也不能无限大,否则也会影响传输的可靠性,而且我们还要考虑接收方的接受能力,你一次性发太多,对面可能接收不过来,就导致丢包率大大增加。
- 尽管引入滑动窗口在一定程度上提高了数据传输的效率,但其本质上是亡羊补牢,因为确保其可靠性就已经注定要是传输效率降低了,不管再怎么优化,也不会比UDP协议传输的效率高的。
快速重传
- 数据的在传输过程中的不确定性是很多的,也就是会发生丢包。丢包发生的情况有两种,第一种则是接收方发送的ACK报文丢了。不过这种情况不影响,因为我可以通过下一个确认应答来确保我之前的数据已经收到了。那如果全部都丢包了呢?其实不会,如果全部丢包的话,那么丢包率就是100%,这还上什么网啊,这明显没网了,下图的丢包率为50%,50%已经很大了,可以认为此时网络出现严重故障,可以断开连接了。
- 第二种则是发送方发送的数据丢包了,如果发送方的数据丢包了,我接收方是可以知道的,因为接收方这边有一个队列,好比我1001-2000这个数据包丢了,那么我1-1000和2001-3000之间就有一个空位了,就可以知道1001-2000这个数据包丢失了。
- 💎此时接收方会一直发送1001ACK报文,但是发送方开始还不以为然,继续发送着后面序号的数据包,接收方尽管在一直发送1001ACK报文,但是接收方还是接收数据的,只是我一直发送1001ACK报文而已;然后,发送方这边就发现接收方怎么一直发这个1001ACK报文啊,然后发送方就顿悟了,哦~,原来是1001-2000这个数据包丢失了啊,那我再发一遍就好了,发送成功后,接收方接收到了,假如我发送方之前一直在发送后面的数据,发送到了6001-7000,那么我接收方接收到1001-2000数据包后,就直接发送7001ACK报文即可,就表示我7001以前的数据肯定到了。接收方的这个过程便是快速重传。
- ✨快速重传是一种优化的重传机制,用于TCP协议中。它通过提前检测数据包丢失并快速重传数据包,避免等待超时,从而提高数据传输效率。在标准的超时重传机制中,发送方需要等待一个超时时间来确认数据包是否丢失。如果丢包发生但网络较快,等待超时会导致不必要的延迟。快速重传可以在没有超时的情况下,通过接收方发送的重复确认(Duplicate ACKs)来检测数据丢失,迅速重传丢失的数据。
- ACK确认机制: 当接收方收到一个乱序的数据包时,会重复发送上次确认的ACK(称为重复ACK ),表明缺少某个数据包。检测丢包: 发送方接收到连续3个重复ACK 时,会认为某个数据包丢失。快速重传: 发送方立即重传丢失的数据包,而不等待超时。**恢复正常传输:**当接收方收到重传的数据包后,恢复正常的ACK确认,发送方继续滑动窗口。
- 快速重传可以减少等待时间: 无需等待超时时间即可发现丢包并重传。提高效率: 提高了数据传输的实时性和吞吐量。减少资源浪费: 避免超时触发的重传数据过多的问题。快速重传与超时重传机制并不矛盾,只是针对不同场合下的不同解决方式。
流量控制
- ✨流量控制是计算机网络中发送方和接收方之间的一种协调机制,用于防止发送方过快地发送数据,超过接收方的处理能力,从而避免数据丢失和资源浪费。
- 由于接收方能力有限 ,接收方的处理速度和缓存大小可能有限,无法快速处理大量数据。或者网络负载: 发送方如果发送过多的数据,可能导致网络拥塞。流量控制也可以保证保证可靠性: 需要确保发送的数据不会因接收方处理能力不足而丢失。流量控制的核心目标是:让发送方的数据传输速率与接收方的处理能力相匹配。
- 前面提到,滑动窗口的大小不能无限大,因为数据过多的发送的话,接收方可能一时半会儿接收不过了,导致数据丢包了。所以我们需要根据接收方接收的能力来动态调整窗口的大小。
- 发送方维护一个窗口,窗口内的数据包可以连续发送,无需等待每个数据包的ACK。接收方通过ACK通知发送方哪些数据已经成功接收。窗口大小由接收方的缓存大小决定,称为"接收窗口"。这样做可以提高数据传输效率,支持连续发送。动态调整窗口大小,根据接收方能力和网络状况优化传输。
- 那接收方应该如何让发送方知道我当前可以处理多少数据呢?发送方的窗口大小又应该如何调整呢?让我们回到TCP协议首部报文格式,我们看到了16位窗口大小的字段,没错,这个字段就是将接收方缓冲区剩余空间大小填入到这个字段中,发送方拿到ACK报文后,就会根据这个字段的大小来动态调整窗口大小。
- 但是,16位窗口大小最大是64kb,有没有可能接收方剩余缓冲区的大小大于64kb呢?虽然几率不大,但还是有可能的,所以,为了避免出现UDP协议同样的错误,TCP这边作了扩展的功能,在选项字段中,有一个窗口扩展因子,窗口扩展因子为2位,所以,实际窗口大小最大其实是256kb,这个就挺大的了,一般也不可能超过256kb。
- 通过上述图解,当接收方缓冲区满时,发送方会停止发送,但是不可能一直停止,所以,发送方会在停止一段时间后发送一个窗口探测包,这个窗口探测包一般不携带实际数据,只是触发一下接收方的ACK报文,看看此时接收缓冲区的大小,随后再根据这个大小继续动态调整窗口的大小。
拥塞控制
- 流量控制是根据接收方的接受能力来动态调整窗口的大小,但是数据在传输过程中,还要经过多个节点的转发,不可能说我直接就到你接收方这里。每个设备都有接收缓冲区,每个设备接收数据能力的大小都不同,所以,我们需要根据整一个数据链路来调整发送方一次性发送多少数据,也就是根据整一个数据链路来动态调整窗口大小。这便是拥塞控制。
- ✨拥塞控制 是计算机网络中的一种机制,用于防止网络因过载而性能下降。它通过调整发送方的数据发送速率来避免网络拥塞,并在拥塞发生后恢复网络的正常运行。网络资源是有限的 ,网络中的带宽、路由器缓存等资源是有限的,如果发送方发送过多的数据,会导致网络资源耗尽。由于网络性能下降 ,拥塞会导致数据丢包、延迟增加,从而降低网络传输效率。拥塞控制可以保证公平性 ,避免单一连接占用过多资源,影响其他连接的正常通信。拥塞控制的核心目标是:在保证网络资源高效利用的前提下,避免拥塞的发生,并在发生拥塞时快速恢复。
- 如何调整这个窗口大小是整个传输的关键,我们采用做实验的方式:一开始先以一个较小的窗口大小发送,发现很顺利,几乎不怎么丢包,那么就不断增大窗口大小,随后发现丢包率增大了,就减小窗口,如此反复,便可以动态控制窗口的大小。
拥塞控制的常见方法
TCP 协议实现了多种拥塞控制算法,其中核心机制包括:
(1)慢启动(Slow Start)
- **原理:**刚开始发送时,发送方假定网络未拥塞,从小规模开始逐步增加发送速率。发送窗口从 1 个数据包开始,每收到一个 ACK,窗口大小加倍,呈指数增长。
- **优点:**可以快速探测网络容量。
- **缺点:**容易导致网络拥塞。
(2)拥塞避免(Congestion Avoidance)
- 原理: 当窗口大小接近网络容量时,改为线性增长,即每次收到一个 ACK,窗口增加 1。
- **目的:**防止网络拥塞。
(3)快重传(Fast Retransmit)
- **原理:**如果发送方收到 3 次重复的 ACK,就认为该数据包丢失,立即重传,而不必等待超时。
- **优点:**减少了丢包引起的延迟。
(4)快恢复(Fast Recovery)
- **原理:**在快重传后,直接将发送窗口减半,而不是回到慢启动的初始值。
- **优点:**提高了拥塞恢复后的效率。
拥塞窗口 是 TCP 中一个动态变化的窗口大小,反映了网络当前允许的发送数据量。
发送方的实际发送窗口为:
实际窗口 = min(接收窗口, 拥塞窗口)
- 接收窗口(Receiver Window): 表示接收方的缓存能力。
- 拥塞窗口(Congestion Window): 表示网络当前的承载能力。
拥塞控制的四个阶段
慢启动:
- 拥塞窗口从 1 开始,每次收到 ACK 后窗口大小加倍。
- 当窗口达到一个阈值(慢启动阈值,
ssthresh
)时,进入拥塞避免。拥塞避免:
- 拥塞窗口开始指数增长,每次收到 ACK,窗口增加 1。
拥塞发生:
- 如果发生超时或 3 次重复 ACK,说明网络拥塞。
- 慢启动: 将
ssthresh
设置为当前窗口的一半,并重置拥塞窗口为 1。快恢复:
- 在快重传后,将拥塞窗口减半,而不是完全重置。
假设一条高速公路:车辆进入高速公路(慢启动): 刚开始允许少量车辆上路,随着路况良好,逐步增加车流量。车流趋于稳定(拥塞避免): 当车流接近高速公路最大承载量时,控制车流增加速度,避免过载。交通堵塞(拥塞发生): 如果某个路段出现事故(丢包),需要减少车辆上路,缓解拥堵。恢复通行(快恢复): 事故清理后,逐步恢复车流量,而不是一开始就允许全部车辆上路。
常见拥塞控制算法:
**Tahoe:**丢包后回到慢启动阶段,较为保守。
**Reno:**引入了快恢复机制,在丢包后只减半窗口,而不是完全重置。
**Cubic:**广泛用于现代网络,改进了在高带宽-高延迟网络中的表现。
**BBR(Bottleneck Bandwidth and Round-trip propagation time):**谷歌开发的一种新型算法,基于带宽和延迟优化,提升了网络传输效率。
特性 流量控制 拥塞控制 目的 防止接收方处理能力不足 防止网络发生拥塞 对象 发送方与接收方之间 网络中所有流量 实现方式 基于接收方的反馈 基于网络状态的反馈
- TCP协议的机制还有很多哦,下节我们将继续深入TCP协议的机制~~~
- 毕竟不知后事如何,且听下回分解
- ❤️❤️❤️❤️❤️❤️❤️