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; //判断子序列是否含有EOF
    std::size_t _eof_index = 0; //记录EOF段最后一个字节的位置

    ByteStream _output;  //!< The reassembled in-order byte stream
    size_t _capacity;    //!< The maximum number of bytes

  public:
    //! \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 stream
    void 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 assembled
    bool 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;
    }
    
    //检查eof
    if(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; }

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

XL5300 dTOF测距模块 加镜头后可达7.6米测距距离 ±4%测距精度

XL5300 直接飞行时间&#xff08;dToF&#xff09;传感器是一个整体方案dTOF 模组&#xff0c;应用设计简单。片内集成了单光子雪崩二极管&#xff08;SPAD&#xff09;接收阵列以及VCSEL激光发射器。利用自主研发的 SPAD 和独特的ToF 采集与处理技术&#xff0c;XL5300模块可实…

无线麦克风哪个品牌音质最好,领夹麦克风品牌排行榜前十名推荐

​在数字化时代的背景下&#xff0c;声音的传播与记录变得日益重要。无论是会议室、教室还是户外场所&#xff0c;无线领夹麦克风凭借其便携性和稳定的连接性能&#xff0c;成为人们沟通表达的首选工具。面对众多选择&#xff0c;我为你精选了几款性能卓越且性价比高的无线领夹…

Minillama3->pt训练

GitHub - leeguandong/MiniLLaMA3: llama3的迷你版本,包括了数据,tokenizer,pt的全流程llama3的迷你版本,包括了数据,tokenizer,pt的全流程. Contribute to leeguandong/MiniLLaMA3 development by creating an account on GitHub.https://github.com/leeguandong/MiniLL…

org.springframework.boot:spring-boot-starter-parent:pom:2.3.4.RELEAS

前言 git上拉了一个项目构建过程中无论是clean还是install都报错 注&#xff1a;很看不惯某博主一点简单的经验分享都要开VIP才能查看的作风 org.springframework.boot:spring-boot-starter-parent:pom:2.3.4.RELEASE failed to transfer from https://maven.aliyun.com/rep…

关于INCA的几个实用功能

01--VUI窗口设计 这个可以按照自己的想法设计INCA观测或标定窗口 首先进入到INCA的环境内&#xff0c;点击实验→加载VUI窗口 选择空的窗口 打开后如下所示&#xff1a; 点击UI开发模式&#xff0c;如下图 如下&#xff1a; 添加标定量、观测量、示波器 窗口的大小需要在开发…

破除“数据孤岛”新策略:Data Fabric(数据编织)和逻辑数据平台

今天&#xff0c;我们已经进入到一个数据爆发的时代&#xff0c;仅 2022 年&#xff0c;我国数据产量就高达 8.1ZB&#xff0c;同比增长 22.7%&#xff0c;数据产量位居世界第二。数据作为新型生产资料&#xff0c;是企业数智化运营的基础&#xff0c;已快速融入到生产、分配、…

资源宝库网站!人人必备的神器!

面对网络中海量的内容&#xff0c;一个高效、便捷的网络导航工具&#xff0c;可以帮助我们快速查找使用网络资源。无论是职场精英还是学生党&#xff0c;使用导航网站都可以帮助我们提升效率。下面小编就来和大家分享一款资源宝库网站-办公人导航-实用的办公生活导航网站&#…

C++240618

1> 思维导图 2> 完善对话框&#xff0c;点击登录对话框&#xff0c; 如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出**提示”登录成功“** &#xff0c;提供一个 **OK按钮**&#xff0c;用户点击**OK后**&#xff0c;**关闭登录界面**&#xff0c; 跳转…

【AI】如何改换Ollama的模型存储位置

【背景】 ollama在构筑AI应用时是用于统一管理模型库的核心组成部分。默认存放ollama模型库的位置是C盘的用户文件夹的.llama-》model下。但是这样C盘很容易占满。 插一句话&#xff0c;越来越觉得不分区有不分区的方便。 好了&#xff0c;有没有办法改变ollama的默认模型存放…

HarmonyOS 角落里的知识 —— 状态管理

一、前言 在探索 HarmonyOS 的过程中&#xff0c;我们发现了许多有趣且实用的功能和特性。有些总是在不经意间或者触类旁通的找到。或者是某些开发痛点。其中&#xff0c;状态管理是ArkUI开发非常核心的一个东西&#xff0c;我们进行了大量的使用和测试遇到了许多奇奇怪怪的问…

欢度盛夏,畅享清凉——七月超市营销策略

随着七月的到来&#xff0c;我国大部分地区进入夏季&#xff0c;气温逐渐攀升&#xff0c;消费者们对清凉、消暑产品的需求也随之增长。在这个夏日&#xff0c;超市应该如何抓住这一商机&#xff0c;提升销售业绩呢&#xff1f;本文将从商品陈列、促销活动等方面&#xff0c;为…

docker安装rabbitmq和延迟插件(不废话版)

1.下载镜像 docker pull rabbitmq:3.8-management 2.启动 docker run -e RABBITMQ_DEFAULT_USERlicoos -e RABBITMQ_DEFAULT_PASSlicoosrabbitmq -v mq-plugins:/plugins --name mq --hostname mq -p 15672:15672 -p 5672:5672 -d rabbitmq:3.8-management 3.下载对…

基于SpringBoot的社区医院管理服务系统

开头语&#xff1a;你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;Eclipse&#xff0c;Navicat&#xff0c;Maven…

Mobvista汇量科技解析奥运机会点及营销理念,看广告投放如何抢占先机

四年一度的奥运盛会&#xff0c;作为少有能跨越文化、宗教、种族、行为等各方面差异的体育事件&#xff0c;更能广泛吸引全球观众的目光&#xff0c;成为品牌方和广告主天然的流量磁铁。应用增长平台Mobvista汇量科技为助力各行业开发者、各品牌商家抢占奥运流量&#xff0c;分…

mp4怎么转换成mp3?这四种转换方法你肯定能用到!

mp4怎么转换成mp3&#xff1f;MP4&#xff0c;这一广为人知的数字多媒体文件格式&#xff0c;无疑已经成为了当下最受欢迎的选择之一&#xff0c;但你是否深入了解过它背后的魅力所在呢&#xff1f;今天&#xff0c;就让我为你揭开MP4的神秘面纱&#xff0c;首先&#xff0c;MP…

ThinkPHP5大学生社会实践管理系统

有需要请加文章底部Q哦 可远程调试 ThinkPHP5大学生社会实践管理系统 一 介绍 大学生社会实践管理系统基于ThinkPHP5框架开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈&#xff1a;ThinkPHP5mysqlbootstrapphpstudyvscode 二 功…

10 种语言文本准确渲染;Mac无需联网的本地聊天应用;多模态语言模型(MLM)基准测试的引擎;Yolo DotNet版本

✨ 1: Glyph-ByT5 10 种语言文本准确渲染&#xff0c;将文本渲染的准确性从提高到近 90% &#xff0c;同时还能实现段落渲染自动布局 Glyph-ByT5是一种定制的文本编码器&#xff0c;旨在实现准确的文字视觉渲染。其核心思想是通过细致的字形-文本配对数据集的微调&#xff0c…

商淘云:服装实体店引流会员营销方案

服装零售实体店面临着越来越大的挑战&#xff0c;尤其是在吸引和保持忠诚顾客方面。为了应对这一挑战&#xff0c;制定一套有效的引流会员营销方案显得尤为重要。商淘云将探讨如何通过创新的营销策略和增强的顾客体验&#xff0c;提升实体店的会员数量和销售业绩&#xff0c;从…

【精品方案】产业园区数字孪生规划方案(39页PPT)

引言&#xff1a;随着数字化和智能化技术的快速发展&#xff0c;传统产业园区面临着转型升级的重大机遇。数字孪生技术作为一种将物理世界与数字世界紧密结合的创新技术&#xff0c;为产业园区的规划、建设和运营管理提供了全新的解决方案。本方案旨在通过构建产业园区数字孪生…

C# WinForm —— 36 布局控件 GroupBox 和 Panel

1. 简介 两个可以盛放其他控件的容器&#xff0c;可以用于把不同的控件分组&#xff0c;一般不会注册事件 GroupBox&#xff1a;为其他控件提供可识别的分组。可通过Text属性设置标题&#xff1b;有边框&#xff1b;没有滚动条&#xff0c;一般用于按功能分组 Panel&#xff…