TCP_滑动窗口介绍

简介

TCP协议中有两个窗口,滑动窗口和拥塞窗口,两者均是一种流控机制;滑动窗口是接收方的流控机制,拥塞窗口是发送方的流控机制。
本文介绍滑动窗口,接收方为TCP连接设置了接收缓存。当TCP连接接收到正确、按序的字节后,会将其放入到接收缓存中,相应的程序从缓存中接收数据。

下图是接收缓存的示意图,其中LastByteRcvd表示从网络中接收并已存入缓存的数据流的最后一个字节编号,LastByteRead是应用进程从缓存中读取的数据流的最后一个字节编号;
接收窗口(rwnd) = receive buffer - (LastByteRcvd - LastByteRead)
在这里插入图片描述

接收窗口,表示接收方当前可接收的数据容量的上限;接收方会将该信息同步给发送方,以使发送方基于该信息协调发送速度,以防止发送速度过快或者过慢而导致的资源损耗。
接收方、发送方均会维护该窗口信息,分别称为接收窗口(rwnd)和发送窗口(swnd);发送窗口(的大小),我们可以理解为接收窗口的一个快照,一个同步有时延的快照。由于他们在处理数据过程中像窗口一样在滑动,故统称为滑动窗口。

ps:如果启用了SACK机制,接收方接收到的数据不连续的情况下,rwnd需要包含空隙的大小。RFC中并未明确规定对于乱序的数据包如何处理(丢弃或缓存),即使未启用SACK机制,某些实现可能也会缓存下来。

用途

  • 流量控制;防止发送方过快的发送数据,超出接收方的处理能力,无效的传输导致资源损耗;
  • 提高吞吐量:定义发送方可允许的最大在途流量(即连续发送的数据量),从而提高数据传输的吞吐量;(和拥塞窗口共同协作来控制发送速度)

实现方式

滑动窗口包括发送窗口(send window)和接收窗口(receive window),其实现涉及两个关键参数:窗口大小和确认机制;
窗口大小,表示可以连续发送或接收的数据量,通过动态调整窗口大小,来控制传输效率。
确认机制,接收方通过发送确认信息来告知发送方已经成功接收的数据范围。

发送窗口示意图如下:
在这里插入图片描述
在这里插入图片描述

接收窗口示意图如下:
在这里插入图片描述
在这里插入图片描述

名词解释:
在这里插入图片描述

窗口大小的通告过程

由于tcp是全双工通讯,通讯双方互为发送、接收方,在交互过程中均会通告其接收窗口的大小;
tcp header中,有两个参数和滑动窗口大小有关,它们是window和window scale;
window在每个报文中会进行通告;
window scale只会在syn报文中进行协商,但对自身(syn报文)不生效,只对后面的报文生效;发送方如果支持window scale机制,在发起syn请求时会携带该信息并填写不为0的值,当接收方在syn+ack报文中同样携带该参数且值不为0,说明双方均支持该机制,参数生效;

真实接收窗口大小 = Window * 2^window_scale;如果不支持window scale机制,则使用Window的值;
下图体现了window scale协商过程,也包含了窗口大小调整的现象;
在这里插入图片描述

调整和流控

下图是窗口大小调整的过程,当接收方来不及处理时,通过调整接收窗口的大小以达到限流的目的。
在这里插入图片描述

零窗口(zero window)

零窗口(Zero Window)是指在TCP通信中,接收端通知发送端其当前没有足够的缓冲区空间来接收更多的数据,从而将接收窗口设置为0的一种状态。

当接收端的滑动窗口大小变为0时,它会向发送端发送一个窗口更新报文段,其中包含了窗口大小为0的信息。

出现零窗口的原因可能是:

  1. 接收端的应用程序来不及处理接收到的数据;这可能是因为应用程序正在执行其他任务,或者因为应用程序本身的处理速度较慢。

  2. 接收端希望暂停数据接收;在某些情况下,接收端可能会主动要求停止数据传输,例如为了释放网络资源或进行其他操作。

当发送端接收到零窗口通告后,它会采取以下行动:

  1. 停止发送新的数据段,直到接收端重新打开窗口;

  2. 启用坚持定时器(Persist Timer),该定时器定期向接收端发送探测报文,询问是否可以继续发送数据。这些探测报文被称为“窗口探测”或“零窗口探测”。

零窗口状态是一个重要的TCP流量控制机制,通过这种方式,发送端可以避免在接收方拥塞时继续发送数据,导致更多的丢包和重传。

在这里插入图片描述

糊涂窗口综合症(Silly Window Syndrome)

糊涂窗口综合症(Silly Window Syndrome, SWS)是指一种低效率的数据传输现象。

它可以出现在接收、发送端的任何一方。当接收方可以通告一个小窗口,发送方可以选择发送少量的数据,这种情况下数据有效载荷率很低,大部分网络带宽被用于传输头部信息。
在这里插入图片描述

下图是一个接收方通告小窗口的示例:

在这里插入图片描述

糊涂窗口综合征通常可以通过以下方式解决:

  1. 发送端避免发送太小的数据段,例如通过Nagle算法合并小数据段;

  2. 接收端尽可能增大其接收窗口,以便能够处理更大的数据段;

  3. 使用TCP的延迟确认机制来减少不必要的确认消息。

参考资料

附*系列文章索引

整理起因
报文分析
报文格式解读
握手+挥手过程状态变化分析
滑动窗口介绍
可靠数据传输原理
拥塞控制
网络异常案例(123456
结束语

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TCP滑动窗口是一种流量控制机制,用于控制发送方和接收方之间的数据流量。它允许发送方在不等待确认的情况下发送多个数据包,而接收方可以根据自己的处理能力和可用缓冲区大小来控制数据的接收速度。 TCP滑动窗口的大小由接收方动态调整,以反映其可用的缓冲区大小。当接收方收到数据时,它会发送一个确认消息,其中包含一个窗口大小值。这个值告诉发送方可以发送多少数据,而不必等待确认消息。 发送方维护一个发送窗口,它是一个连续的字节序列,表示可以发送但尚未得到确认的数据。发送方根据接收方发送的窗口大小值来调整发送窗口的大小。如果接收方的窗口大小值为0,发送方将停止发送数据,直到接收方发送一个非零的窗口大小值。 当发送方收到一个确认消息时,它会将发送窗口向前滑动,以删除已确认的数据,并将新的未确认数据添加到发送窗口中。这个过程不断重复,直到所有数据都被确认。 下面是一个简单的TCP滑动窗口的例子: ```python # 假设接收方的窗口大小为10 window_size = 10 # 发送方的发送窗口 send_window = b"0123456789abcdefghijklmnopqrstuvwxyz" # 发送方已经发送但未确认的数据 unacked_data = b"" # 发送方已经发送并确认的数据 acked_data = b"" # 模拟发送数据 while send_window: # 如果接收方的窗口大小为0,停止发送数据 if window_size == 0: break # 计算可以发送的数据大小 data_size = min(len(send_window), window_size) # 从发送窗口中取出数据 data = send_window[:data_size] # 将数据添加到未确认数据中 unacked_data += data # 从发送窗口中删除已经发送的数据 send_window = send_window[data_size:] # 更新窗口大小 window_size -= data_size # 模拟发送数据 # send(data) # 模拟接收确认消息 while unacked_data: # 模拟接收确认消息 # ack = receive_ack() ack = True if ack: # 从未确认数据中删除已经确认的数据 acked_data += unacked_data[:window_size] unacked_data = unacked_data[window_size:] # 更新窗口大小 window_size += len(acked_data) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值