news 2026/8/16 3:28:49

滑动窗口技术详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
滑动窗口技术详解

滑动窗口技术详解

目录

  1. 滑动窗口的核心思想
  2. 不同协议中的具体做法
  3. 优势与局限
  4. TCP 滑动窗口工作流程示意
  5. 通用滑动窗口 C++ 实现
  6. 总结

一、滑动窗口的核心思想

滑动窗口是一种用于流量控制可靠传输的技术,主要解决以下问题:

  1. 提高信道利用率:允许发送方在未收到确认的情况下连续发送多个数据单元,而不是每发一个就停下来等待确认。
  2. 控制流量:接收方可以通过窗口大小告知发送方自己当前能接收的数据量,防止接收方缓冲区溢出。
  3. 实现按序交付与重传:窗口内的分组按顺序编号,接收方根据序号判断是否有丢包,发送方根据确认信息决定重传哪些分组。

基本机制

  • 发送方维护一个发送窗口,表示可以发送但还未被确认的分组范围。
  • 接收方维护一个接收窗口,表示可以接收的分组范围。
  • 窗口会随着数据的发送、确认以及超时事件向前「滑动」,因此称为滑动窗口

二、不同协议中的具体做法

2.1 TCP(Transmission Control Protocol)

TCP 是滑动窗口最经典的应用场景之一。

  • 发送窗口:由**拥塞窗口(cwnd)接收方通告窗口(rwnd)**共同决定,实际可用窗口 = min(cwnd, rwnd)
  • 接收窗口:接收方在 ACK 报文中通告自己剩余的缓冲区大小。
  • 滑动过程:每收到一个 ACK,窗口左边界右移;新数据被确认后,窗口整体向右滑动。
  • 特点:支持可变窗口大小、流量控制、拥塞控制(慢启动、拥塞避免等)。

2.2 HDLC(High-Level Data Link Control)

HDLC 是面向比特的数据链路层协议,使用固定长度的滑动窗口进行流量控制。

  • 窗口大小:由协议参数 W 决定,W=7 表示可连续发送 7 帧而不需确认。
  • 确认方式:可以是捎带确认(piggybacking)或单独的 RR(Receive Ready)帧。
  • 滑动过程:收到对第 N 帧的确认后,窗口向前滑动到第 N+1 帧。

2.3 PPP(Point-to-Point Protocol)

PPP 在数据链路层也使用类似滑动窗口的机制(在 LCP 协商阶段可启用)。

  • 窗口大小:可配置,通常为 1(无流量控制)或更大。
  • 确认与重传:使用超时重传机制,窗口滑动依赖于收到正确的确认帧。

2.4 X.25 分组交换网络

X.25 在数据链路层和分组层都使用滑动窗口。

  • 链路层:类似 HDLC,使用固定窗口大小。
  • 分组层:窗口大小可动态协商,用于控制端到端的数据流。

2.5 实时通信与多媒体协议(如 RTP/RTCP 扩展)

RTP 本身不强制滑动窗口,但在某些实现中,为处理网络抖动和丢包,会采用类似滑动窗口的缓冲区管理策略,对接收到的数据包进行有序重组和播放。


三、优势与局限

优势

  • 提高信道利用率,减少等待时间。
  • 提供流量控制,防止接收方过载。
  • 便于实现可靠传输和重传机制。

局限

  • 需要维护窗口状态,增加协议复杂度。
  • 在高速网络中,窗口大小可能成为性能瓶颈(需配合拥塞控制算法)。
  • 对乱序到达的处理需要额外机制(如选择重传 SACK)。

四、TCP 滑动窗口工作流程示意

4.1 基本概念

在 TCP 中,发送窗口由两部分组成:

  • 已发送但未确认(In-Flight)
  • 可以发送但尚未发送(Available)

窗口大小 = min(拥塞窗口 cwnd, 接收方通告窗口 rwnd)

4.2 初始状态示例

假设窗口大小为 5,序列号范围 0~4,初始时发送方已发送 Seq=0、1,未收到确认:

发送窗口: [0][1][2][3][4] ↑ ↑ 左边界 右边界 已发送未确认 可发送

4.3 流程步骤

Step 1:初始发送
发送方发送 Seq=0、Seq=1,此时已发送未确认:0,1;可发送:2,3,4。

Step 2:收到部分确认
收到 ACK=2(表示 Seq=0,1 已收到),窗口左边界滑动到 2;已发送未确认为空,可发送:2,3,4 及新序号 5,6。

Step 3:继续发送
发送 Seq=2、Seq=3,已发送未确认:2,3;可发送:4,5,6。

Step 4:收到累积确认
收到 ACK=4(Seq=2,3 已收到),左边界滑到 4;可发送:4,5,6,7,8。

Step 5:超时重传
若 Seq=4 超时未确认,发送方重传 Seq=4,窗口不变直到收到 ACK;已发送未确认:4(重传);可发送:5,6,7,8。

Step 6:接收方窗口变化
若接收方缓冲区变小,通告 rwnd=3,则发送窗口上限缩小;左边界=4 时右边界不能超过 6,可发送只有 4,5,6。

4.4 关键点总结

  1. 窗口滑动:每次收到 ACK,左边界右移;右边界随发送新数据或窗口大小调整而移动。
  2. 流量控制:接收方通过 rwnd 限制发送速率。
  3. 拥塞控制:cwnd 根据网络状况动态调整,与 rwnd 共同决定实际窗口。
  4. 重传机制:超时或收到重复 ACK 时触发重传,窗口暂时不滑动。

五、通用滑动窗口 C++ 实现

以下为通用的 C++ 滑动窗口实现模板,不依赖具体协议,仅实现核心的发送窗口管理逻辑:窗口初始化与动态调整、数据发送与确认、窗口滑动、超时重传检测。可基于此适配 TCP、HDLC 等协议。

#include<iostream>#include<unordered_map>#include<queue>#include<string>#include<chrono>#include<thread>// 模拟数据包结构structPacket{intseq_num;std::string data;boolis_acked;std::chrono::steady_clock::time_point send_time;};classSlidingWindow{private:intwindow_size;intbase;intnext_seq_num;std::unordered_map<int,Packet>unacked_packets;std::queue<Packet>packet_buffer;public:SlidingWindow(intsize):window_size(size),base(0),next_seq_num(0){}voidadd_data_to_send(conststd::string&data){packet_buffer.push({next_seq_num,data,false,std::chrono::steady_clock::now()});next_seq_num++;}voidtry_send(){while(unacked_packets.size()<window_size&&!packet_buffer.empty()){Packet pkt=packet_buffer.front();packet_buffer.pop();pkt.send_time=std::chrono::steady_clock::now();unacked_packets[pkt.seq_num]=pkt;std::cout<<"发送数据包: Seq="<<pkt.seq_num<<", Data="<<pkt.data<<std::endl;}}voidreceive_ack(intack_num){if(ack_num>base){for(inti=base;i<ack_num;++i){unacked_packets.erase(i);}base=ack_num;std::cout<<"收到 ACK="<<ack_num<<", 窗口滑动到 base="<<base<<std::endl;}else{std::cout<<"收到重复 ACK="<<ack_num<<std::endl;}}voidcheck_timeout(inttimeout_ms=1000){autonow=std::chrono::steady_clock::now();for(auto&[seq,pkt]:unacked_packets){autoelapsed=std::chrono::duration_cast<std::chrono::milliseconds>(now-pkt.send_time).count();if(elapsed>timeout_ms){std::cout<<"超时重传: Seq="<<seq<<std::endl;pkt.send_time=now;}}}voidprint_status(){std::cout<<"当前窗口: base="<<base<<", next_seq="<<next_seq_num<<", 未确认包数量="<<unacked_packets.size()<<std::endl;}};intmain(){SlidingWindowsw(3);sw.add_data_to_send("Hello");sw.add_data_to_send("World");sw.add_data_to_send("TCP");sw.add_data_to_send("Protocol");sw.try_send();sw.print_status();std::this_thread::sleep_for(std::chrono::milliseconds(500));sw.receive_ack(2);sw.try_send();sw.print_status();std::this_thread::sleep_for(std::chrono::milliseconds(1200));sw.check_timeout(1000);return0;}

代码说明

  • SlidingWindow 类window_size为最大可发送未确认数量;base为窗口左边界;next_seq_num为下一个要分配的序列号;unacked_packets记录已发送未确认的包;packet_buffer模拟待发送数据。
  • 主要方法add_data_to_send添加数据;try_send在窗口未满时发送;receive_ack处理确认并滑动窗口;check_timeout检测超时并重传;print_status打印状态。
  • 可扩展:可加入拥塞控制(动态调整window_size)、SACK 支持,以及替换为真实网络 I/O。

六、总结

滑动窗口的核心思想是通过维护一个可动态调整的发送/接收范围,实现高效、可控的数据传输。它在TCP、HDLC、PPP、X.25等协议中都有不同的实现方式,但目标一致:在保证可靠性的前提下最大化信道利用率

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/9 23:10:01

红外性诱测报仪红外性诱测报灯红外靶向害虫自动测报系统

靶向测报系统的核心定位是什么&#xff1f;和传统虫情监测设备相比&#xff0c;最大的优势是什么&#xff1f;答&#xff1a;核心定位是构建虫情智慧大脑&#xff0c;主打“精准测报情报分析”&#xff0c;而非单纯的杀灭害虫——它更擅长捕捉虫情“情报”&#xff0c;为防控决…

作者头像 李华
网站建设 2026/8/9 23:11:21

云计算基础详解:容器与云原生的核心逻辑及实践价值

云计算基础详解&#xff1a;容器与云原生的核心逻辑及实践价值 在云计算飞速发展的今天&#xff0c;“容器”和“云原生”早已不是陌生的技术名词——从互联网大厂的大规模服务部署&#xff0c;到中小企业的数字化转型&#xff0c;它们正在重塑应用开发、部署与运维的全流程。但…

作者头像 李华
网站建设 2026/8/9 23:09:44

探索 6 机 30 节点电力系统的混合规划求解

基于混合规划求解6机30节点的机组启停情况以及支路与节点的功率情况&#xff0c;有说明文档&#xff0c;精品代码&#xff0c;考虑安全约束与热备用。在电力系统的研究与运行优化中&#xff0c;精确求解机组启停情况以及支路与节点的功率情况是至关重要的。今天咱们就来聊聊基于…

作者头像 李华
网站建设 2026/7/31 5:54:21

金融风控测试新范式:因果发现算法优化误报率的实战路径

2026年金融科技监管趋严背景下&#xff0c;反欺诈模型误报率每降低1%可节省千万级运营成本&#xff08;某银行实测数据&#xff09;&#xff0c;但传统特征工程面临特征混杂性难题。因果发现算法通过识别欺诈行为的真实诱因&#xff0c;为测试人员提供可解释的优化路径。 一、误…

作者头像 李华
网站建设 2026/7/28 6:19:36

我终于能够在 Debian 13 上享受 KDE 6了,桌面稳定到让人尖叫

过去一年,我几乎把所有主流发行版都试了个遍,就为了让 KDE Plasma 6 在我的机器上“正常运行”。Arch、Fedora KDE、Kubuntu、openSUSE Tumbleweed、Neon……能装的我都装了,能调的配置我都调了,但结果呢?每次都卡在同一个致命问题上——颜色渲染诡异得要命,灰色阴影深得…

作者头像 李华