cs144 LAB1 基于滑动窗口的碎片字节流重组器

一.StreamReassembler.capacity 的意义

StreamReassembler._capacity 的含义:

capacity

  • ByteStream 的空间上限是 capacity
  • StreamReassembler 用于暂存未重组字符串片段的缓冲区空间 StreamReassembler.buffer 上限也是 capacity
  • 蓝色部分代表了已经被上层应用读取的已重组数据
  • 绿色部分代表了 ByteStream 中已经重组并写入但还未被读取的字节流所占据的空间大小
  • 红色部分代表了 StreamReassembler 中已经缓存但未经重组的若干字符串片段所占据的空间大小
  • 同时绿色和红色两部分加起来的空间总占用大小不会超过 capacity(事实上会一直小于它)

从代码层面来看:

  • first unread 的索引等于 ByteStream 的 bytes_read() 函数的返回值(我们一般不关注这个值)
  • first unassembled 的索引等于 ByteStream 的 bytes_write() 函数的返回值(起始就是下一个期望的字节在流中的序号)
  • first unacceptable 的索引等于 ByteStream 的 bytes_read() 加上 capacity 的和(已超过 ByteStream 的 buffer 限制)
  • first unread 和 first unacceptable 这两个边界是动态变化的,每次重组结束都需要更新。

最后,有个很重要点,ByteStream 和 StreamReassembler 的总容量有固定的限制,多余的数据需要丢弃(此需要对端重传数据,这就引出了重传等知识点)

二.滑动窗口碎片重组算法 

        每次收到的data数据由于网络传输不可靠的原因会产生乱序,重叠。需要对每次收到的碎片序列进行重组。可以定义装配器的窗口大小为capacity,范围为[_first_unassembled,_first_unassembled + _capacity]。超出此范围的字节将被丢弃(实验要求,之后会引出重传)。窗口会随着第一个期望的字节序号进行移动即_first_unassembled。每次计算缓冲区第一个期望字节序号,并保障每个字节碎片都在窗口范围内,这需要对碎片进行裁剪,裁剪过后的碎片可以直接加入缓存区。

        可分为下面几个步骤完成:

1.计算重组器窗口起始位置,结束位置。

2.判断碎片是否合法,不合法则直接丢弃。

3.裁剪碎片,使其满足缓冲区要求。

4.碎片加入缓存区。

5.缓存区写入流。(如果缓冲区头部有元素的话)

6.判断EOF。

        需要注意EOF这里有几个大坑,首先是EOF可能会提早到来,这时不能直接结束流写入需要进行判断。第二是EOF可能与其他流重叠,故而可以记录EOF的合法结束字节位置来判断是否真正需要停止流写入。

#ifndef SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH
#define SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH#include "byte_stream.hh"#include <cstdint>
#include <string>
#include <deque>//! \brief A class that assembles a series of excerpts from a byte stream (possibly out of order,
//! possibly overlapping) into an in-order byte stream.
class StreamReassembler {private:// Your code here -- add private members as necessary.std::deque<std::string::value_type> _reassembler_buffer;  //重组器缓冲区std::deque<bool> _bytes_flag; //重组器字节标志位std::size_t _unassembaled_bytes = 0;  //未被装配的字节bool _is_eof = false; //判断子序列是否含有EOFstd::size_t _eof_index = 0; //记录EOF段最后一个字节的位置ByteStream _output;  //!< The reassembled in-order byte streamsize_t _capacity;    //!< The maximum number of bytespublic://! \brief Construct a `StreamReassembler` that will store up to `capacity` bytes.//! \note This capacity limits both the bytes that have been reassembled,//! and those that have not yet been reassembled.StreamReassembler(const size_t capacity);//! \brief Receive a substring and write any newly contiguous bytes into the stream.//!//! The StreamReassembler will stay within the memory limits of the `capacity`.//! Bytes that would exceed the capacity are silently discarded.//!//! \param data the substring//! \param index indicates the index (place in sequence) of the first byte in `data`//! \param eof the last byte of `data` will be the last byte in the entire streamvoid push_substring(const std::string &data, const uint64_t index, const bool eof);//! \name Access the reassembled byte stream//!@{const ByteStream &stream_out() const { return _output; }ByteStream &stream_out() { return _output; }//!@}//! The number of bytes in the substrings stored but not yet reassembled//!//! \note If the byte at a particular index has been pushed more than once, it//! should only be counted once for the purpose of this function.size_t unassembled_bytes() const;//! \brief Is the internal state empty (other than the output stream)?//! \returns `true` if no substrings are waiting to be assembledbool empty() const;
};#endif  // SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH
#include "stream_reassembler.hh"// Dummy implementation of a stream reassembler.// For Lab 1, please replace with a real implementation that passes the
// automated checks run by `make check_lab1`.// You will need to add private members to the class declaration in `stream_reassembler.hh`template <typename... Targs>
void DUMMY_CODE(Targs &&... /* unused */) {}using namespace std;StreamReassembler::StreamReassembler(const size_t capacity) : 
_reassembler_buffer(capacity, '\0'),
_bytes_flag(capacity, false),
_output(capacity),
_capacity(capacity) {}//! \details This function accepts a substring (aka a segment) of bytes,
//! possibly out-of-order, from the logical stream, and assembles any newly
//! contiguous substrings and writes them into the output stream in order.
void StreamReassembler::push_substring(const string &data, const size_t index, const bool eof) {//判断index是否合法std::size_t _first_unassembled = _output.bytes_written();   //每次计算期望的字节序号std::size_t _first_unacceptable = _first_unassembled + _capacity;   //第一个不允许装配的字节序号if(index >= _first_unacceptable || index + data.length() < _first_unassembled)return;//滑动窗口位于[_first_unassembled,_first_unassembled + _capacity]之间只有其中元素可以入队,对data进行裁剪std::size_t new_index = index;std::size_t new_end = index + data.length();if(new_index < _first_unassembled)new_index = _first_unassembled;if(new_end >= _first_unacceptable)new_end = _first_unacceptable;//裁剪完成后data的起始位置符合滑动窗口要求,入队for(std::size_t i = new_index; i < new_end; ++i){if(!_bytes_flag[i - _first_unassembled]){_reassembler_buffer[i - _first_unassembled] = data[i - index];   //入队_bytes_flag[i - _first_unassembled] = true;  //相应标志位置位++_unassembaled_bytes;  //缓冲区计数增加}}//写入流操作(当装配缓冲区头部有元素那么一定是顺序的直接写入流)string wait_to_write{};while(_bytes_flag.front()){wait_to_write += _reassembler_buffer.front();_bytes_flag.pop_front();_reassembler_buffer.pop_front();_bytes_flag.emplace_back(false);        //维护缓冲区大小_reassembler_buffer.emplace_back('\0'); //维护缓冲区大小}if(wait_to_write.size() > 0){int out_bytes = _output.write(std::move(wait_to_write));_unassembaled_bytes -= out_bytes;}//检查eofif(eof){_is_eof = true;_eof_index = new_end;}if(_is_eof && _eof_index == _output.bytes_written())_output.end_input();
}size_t StreamReassembler::unassembled_bytes() const { return _unassembaled_bytes; }bool StreamReassembler::empty() const { return _unassembaled_bytes == 0; }

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30182.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神火股份电子商务平台(数字化招采平台),构建企业数字活力

为推进数字化转型升级进程&#xff0c;神火股份携手信源信息建设电子商务平台&#xff0c;近日&#xff0c;该平台已实现验收&#xff0c;为企业高质量发展注入“数字活力”。 河南神火煤电股份有限公司&#xff08;简称“神火股份”&#xff09;是以煤炭、发电、电解铝生产及…

2024年CCSK认证培训招生简章公开

CCSK认证培训背景 本课程旨在确保与云计算相关的从业人员对云安全威胁和云安全最佳 实践有一个全面的了解和广泛的认知。包含了广泛的云安全知识&#xff0c;涵 盖了体系结构、合规治理、加密和虚拟化等主题。自2010年推出以 来&#xff0c;成千上万的IT和安全专业人员通过CCSK…

系统架构理解

一、统一提前查好所有数据后续逻辑用到啥取啥&#xff0c;还是等用到对应数据的时候再查 1、用到啥查啥&#xff1a; 优势&#xff1a;减少依赖调用次数&#xff0c;减轻服务器压力&#xff1b;代码逻辑清晰&#xff0c;没有太多分支判断 劣势&#xff1a;无法避免串行调用&am…

LeetCode题练习与总结:分割回文串--131

一、题目描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 示例 1&#xff1a; 输入&#xff1a;s "aab" 输出&#xff1a;[["a","a","b"],["aa&q…

snmp-check一键获取SNMP信息(KALI工具系列二十一)

目录 1、KALI LINUX 简介 2、snmp-check工具简介 3、在KALI中使用onesixtyone 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、操作示例 4.1 SNMP 检查 4.2 指定 SNMP 端口 4.3 指定社区字符串 4.4 详细输出 4.5 指定多项 5、总结 1、KALI LINUX 简介…

【Vue】登录功能中对于错误提示信息的重构

登录功能中&#xff0c;使用Axios 的响应拦截器对于错误提示进行重构。 原代码: //form实例统一校验 const formRef ref(null); const router useRouter(); const doLogin () > {formRef.value.validate(async (valid) > {// valid: 所有表单都通过校验 才为true//c…

【网络安全产品】---下一代防火墙

再此之前也大概介绍过传统防火墙&#xff0c;waf以及数据库防火墙&#xff0c;今天发现居然没有对下一代防火墙有过学习。。。今天参考一些资料进行整理。。 网络安全产品---数据库防火墙/审计_数据库审计 数据库防火墙-CSDN博客 【网络安全产品】---应用防火墙(WAF)_waf csd…

JavaScript 导致内存泄漏的场景和规避方法

在日常开发中&#xff0c;我们经常会无意识一些操作导致内存溢出。为此我总结一下内存溢出的几种场景供大家参考。希望能在优化自己代码的道路上有所帮助。 1、意外的全局变量 由于使用未声明的变量&#xff0c;而意外的创建了一个全局变量&#xff0c;使这个变量一直留在内存…

Danikor智能拧紧轴控制器过压维修知识

【丹尼克尔拧紧轴控制器故障代码维修】 【丹尼克尔Danikor控制器维修具体细节】 丹尼克尔拧紧轴控制器作为一种高精度的电动拧紧工具&#xff0c;广泛应用于各种工业生产线。然而&#xff0c;在使用过程中&#xff0c;由于各种原因&#xff0c;可能会出现Danikor扭矩扳手控制…

Linux系统编程——部分内容补充

回顾 进程 内核相关数据结构 代码和数据&#xff0c;一个可执行程序加载到内存变成进程&#xff0c;不仅仅是把代码和数据加载进去就完事了&#xff0c;得“先描述&#xff0c;再组织”&#xff0c;每个进程都有内核数据结构&#xff0c;地址空间&#xff0c;进程相关页表&a…

内核学习——5、中断

硬中断&#xff1a; 是一个异步信号&#xff0c;或需要改变执行一个同步事件 外设产生&#xff0c;基于IRQ&#xff0c;CPU将相应请求给到硬件驱动处理事务 处理中断的驱动需要运行在CPU上的&#xff0c;中断产生时&#xff0c;CPU停止当前程序去处理中断请求&#xff0c;一个…

【案例分析】一文讲清楚SaaS产品运营的六大杠杆是什么?具体怎么运用?

在SaaS&#xff08;软件即服务&#xff09;行业&#xff0c;如何快速获取用户并实现持续增长一直是企业关注的重点。近年来&#xff0c;分销裂变策略因其高效性和低成本特性&#xff0c;成为许多SaaS企业实现快速增长的秘诀。下面&#xff0c;我们将通过一个具体的案例来剖析成…

Ubuntu-24.04-live-server-amd64安装界面中文版

系列文章目录 Ubuntu安装qemu-guest-agent Ubuntu-24.04-live-server-amd64启用ssh Ubuntu乌班图安装VIM文本编辑器工具 文章目录 系列文章目录前言一、准备工作二、开始安装三、测试效果总结 前言 Centos结束&#xff0c;转战Ubuntu。我之所以写这篇文章&#xff0c;是因为我…

精细化,智能费控4.0的竞争内核

出差&#xff0c;在百度百科被释义为&#xff0c;受派遣到外地或负担临时任务。 这是一个对员工清晰对管理却笼统的定义。站在企业费用管理的角度&#xff0c;出差可细分为会议出差、培训出差、市场拓展出差、项目出差、驻外回厂出差、探亲出差、售后维修出差、新人报道出差等不…

防爆气象站:化工厂区气象环境监测的最佳选择

在化工厂区&#xff0c;气象环境监测至关重要&#xff0c;它直接关系到生产安全、环境保护以及员工健康。防爆气象站作为专业的监测设备&#xff0c;凭借其独特的防爆性能和精准的数据监测能力&#xff0c;成为化工厂区气象环境监测的最佳选择。 防爆气象站采用先进的防爆技术…

访问网络 测试没有问题,正式有问题

ping -c 5 -i 1 www.baidu.com 首先检查一下网络&#xff0c;在正式服务器ping 一下要访问的地址。 如果不行&#xff0c;联系网络管理员开通。 笔者因为这个问题浪费了半天时间&#xff0c;一开始都以为是代码问题 以后大家看到这个异常&#xff0c;解决如下&#xff1a; …

逻辑卷管理器 (LVM) 简介

古老的 e5 主机目前有这些存储设备 (硬盘): 系统盘 (M.2 NVMe SSD 480GB), 数据盘 (3.5 英寸 SATA 硬盘 4TB x2). 窝决定使用 LVM 对数据盘进行管理. 逻辑卷管理器 (LVM) 可以认为是一种 (单机) 存储虚拟化 技术. 多个物理存储设备 (PV) 组成一个存储池 (VG), 然后划分虚拟分区…

docker ce的使用介绍

docker docker17.03以后 docker ce&#xff0c;社区免费版&#xff0c;vscode的docker插件使用的该版本&#xff08;默认windows只支持windows容器&#xff0c;linux支持linux容器&#xff09;docker ee&#xff0c;企业版本 docker17.03以前 docker toolbox&#xff0c;基于…

手把手带你从异构数据库迁移到崖山数据库

一、数据迁移简介 1.典型场景与需求 在国产化浪潮下&#xff0c;数据库系统的国产化替代成为了一个日益重要的议题&#xff0c;有助于企业降低对外依赖&#xff0c;提升信息安全和自主性。 以Oracle、MySQL为代表的传统关系型数据库管理系统&#xff0c;在企业应用中占据了重要…

angular12父子组件通信的三种方法

在Angular中&#xff0c;父组件可以通过输入属性&#xff08;Input&#xff09;来传递数据给子组件&#xff0c;但是不能直接修改子组件内部的变量&#xff0c;尤其是如果这些变量不是通过输入属性传递的。这是因为在Angular中&#xff0c;子组件的内部状态应该由子组件自己管理…