CS 144 Lab One

news2024/11/27 20:58:36

CS 144 Lab One

  • 实验结构
  • 环境配置
  • 如何调试
  • StreamReassembler 实现


对应课程视频: 【计算机网络】 斯坦福大学CS144课程

Lab 1 对应的PDF: Lab Checkpoint 1: stitching substrings into a byte stream


实验结构

这幅图完整的说明了CS144 这门实验的结构:
在这里插入图片描述
其中, ByteStream 是我们已经在 Lab0 中实现完成的。

我们将在接下来的实验中分别实现:

  • Lab1 StreamReassembler:实现一个流重组器,一个将字节流的字串或者小段按照正确顺序来拼接回连续字节流的模块
  • Lab2 TCPReceiver:实现入站字节流的TCP部分。
  • Lab3 TCPSender:实现出站字节流的TCP部分。
  • Lab4 TCPConnection: 结合之前的工作来创建一个有效的 TCP 实现。最后我们可以使用这个 TCP 实现来和真实世界的服务器进行通信。

该实验引导我们以模块化的方式构建一个 TCP 实现。

流重组器在 TCP 起到了相当重要的作用。迫于网络环境的限制,TCP 发送者会将数据切割成一个个小段的数据分批发送。但这就可能带来一些新的问题:数据在网络中传输时可能丢失、重排、多次重传等等。而TCP接收者就必须通过流重组器,将接收到的这些重排重传等等的数据包重新组装成新的连续字节流。


环境配置

当前我们的实验代码位于 master 分支,而在完成 Lab1 之前需要合并一些 Lab1 的依赖代码,因此执行以下命令:

git merge origin/lab1-startercode

之后重新 make 编译即可。


如何调试

先 cmake && make 一个 Debug 版本的程序。

所有的评测程序位于build/tests/中,先一个个手动执行过去。

若输出了错误信息,则使用 gdb 调试一下。


StreamReassembler 实现

在我们所实现的流重组器中,有以下几种特性:

  • 接收子字符串。这些子字符串中包含了一串字节,以及该字符串在总的数据流中的第一个字节的索引

  • 流的每个字节都有自己唯一的索引,从零开始向上计数。

  • StreamReassembler 中存在一个 ByteStream 用于输出,当重组器知道了流的下一个字节,它就会将其写入至 ByteStream中。

需要注意的是,传入的子串中:

  • 子串之间可能相互重复,存在重叠部分

    • 但假设重叠部分数据完全重复。
    • 不存在某些 index 下的数据在某个子串中是一种数据,在另一个子串里又是另一种数据。
    • 重叠部分的处理最为麻烦。
  • 可能会传一些已经被装配了的数据

  • 如果 ByteStream 已满,则必须暂停装配,将未装配数据暂时保存起来

除了上面的要求以外,容量 Capacity 需要严格限制:

在这里插入图片描述
为了便于说明,将图中的绿色区域称为 ByteStream,将图中存放红色区域的内存范围(即 first unassembled - first unacceptable)称为 Unassembled_strs。

CS144 要求将 ByteStream + Unassembled_strs 的内存占用总和限制在 Reassember 中构造函数传入的 capacity 大小。因此我们在构造 Reassembler 时,需要既将传入的 capacity 参数设置为 ByteStream的缓冲区大小上限,也将其设置为first unassembled - first unacceptable的范围大小,以避免极端情况下的内存使用。

注意:first unassembled - first unacceptable的范围大小,并不等同于存放尚未装配子串的结构体内存大小上限,别混淆了。

Capacity 这个概念很重要,因为它不仅用于限制高内存占用,而且它还会起到流量控制的作用(见 lab2)。

代码实现如下:

  • stream_reassembler.hh
//! \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.
    struct Datum {
        char ch = 0;
        bool valid = false;
    };
    std::vector<Datum> buffer_;  // buffer to store unassembled data.
    size_t buffer_header_;       // pointer to the begining of the unssembled bytes in
                                 // buffer.
    size_t unassembled_bytes_;
    size_t eof_byte_;
    bool is_eof_set_;    // true if read the 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;
};
  • stream_reassembler.cc
#include "stream_reassembler.hh"

#include <cassert>

// 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`

using namespace std;

StreamReassembler::StreamReassembler(const size_t capacity)
    : buffer_(capacity)
    , buffer_header_(0)
    , unassembled_bytes_(0)
    , eof_byte_(0)
    , is_eof_set_(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) {
    if (_output.input_ended())
        return;
    const size_t max_byte = _output.bytes_read() + _capacity;
    const size_t index_start = std::max(_output.bytes_written(), index);
    size_t index_end = std::min(max_byte, index + data.length());
    // check for eof
    if (eof) {
        is_eof_set_ = true;
        eof_byte_ = index + data.length();
    }
    if (is_eof_set_)
        index_end = std::min(index_end, eof_byte_);

    // buffer the data
    for (size_t write_index = index_start; write_index < index_end; write_index++) {
        size_t cache_index = (buffer_header_ + write_index - _output.bytes_written()) % _capacity;
        assert(!(buffer_[cache_index].valid && buffer_[cache_index].ch != data[write_index - index]));
        if (!buffer_[cache_index].valid)
            unassembled_bytes_++;
        buffer_[cache_index].valid = true;
        buffer_[cache_index].ch = data[write_index - index];
    }

    // write the data.
    while (buffer_[buffer_header_].valid) {
        buffer_[buffer_header_].valid = false;
        _output.write_char(buffer_[buffer_header_].ch);
        unassembled_bytes_--;
        buffer_header_ = (buffer_header_ + 1) % _capacity;
    }
    if (is_eof_set_ && _output.bytes_written() >= eof_byte_)
        _output.end_input();
}

size_t StreamReassembler::unassembled_bytes() const { return unassembled_bytes_; }

bool StreamReassembler::empty() const { return unassembled_bytes_ == 0; }

代码可能不太容易理解,但是大家对照下图,把几种可能出现的情况看明白,再回去看代码,相信就不难了:
在这里插入图片描述
测试代码正确性:
在这里插入图片描述

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

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

相关文章

【C++】多线程编程三(std::mutexstd::mutex、std::lock_guard、std::unique_lock详解)

目录 一、线程间共享数据 1.数据共享和条件竞争 2.避免恶性条件竞争 二、用互斥量来保护共享数据 1. 互斥量机制 2.mutex头文件介绍 三、C中使用互斥量mutex 1. 互斥量mutex使用 2.mutex类成员函数 ① 构造函数 ② lock() ③ unlock() ④ try_lock() 四、使用std::…

本地服务器localhost:3000一直连接不上

1.检查使用端口3000的进程: 在Windows上,运行 netstat -ano | findstr :3000在Mac/Linux上,运行lsof -i :3000 这将列出当前使用端口3000的任何进程。您要终止这些进程以释放该端口。 2.检查防火墙规则: 确保您的防火墙允许连接到localhost:3000。在MacOS和Windows上,通常不…

vue2已有项目迁移vue3踩坑记录

升级部分所需package.json版本&#xff0c;如vue及相关ui 参考vue3项目升级 解决运行报错 configureWebpack: {// webpack pluginsplugins: [// Ignore all locale files of moment.js// new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), 修改为new webpack.IgnorePlug…

azkaban

访问地址 https://xxx.xxx.xxx.xx:8443/index启动azkaban cd /data/servers/azkaban/executor ./bin/start-exec.sh cd /data/servers/azkaban/server ./bin/start-web.sh修改访问数据库密码 cd /data/servers/azkaban/executor/confvim azkaban.propertiescd /data/servers…

电脑桌面远程连接?外网远程桌面连接内网服务器穿透设置

自己个人电脑远程桌面连接另台服务器时&#xff0c;就可以使用到远程连接的功能&#xff0c;如在公司网络管理员远程连接ERP服务器管理操作。 远程连接就是在远程连接另外一台计算机。当某台计算机开启了远程桌面连接功能后我们就可以在网络的另一端控制这台计算机了&#xff…

人工智能大语言模型微调技术:SFT 监督微调、LoRA 微调方法、P-tuning v2 微调方法、Freeze 监督微调方法

人工智能大语言模型微调技术&#xff1a;SFT 监督微调、LoRA 微调方法、P-tuning v2 微调方法、Freeze 监督微调方法 1.SFT 监督微调 1.1 SFT 监督微调基本概念 SFT&#xff08;Supervised Fine-Tuning&#xff09;监督微调是指在源数据集上预训练一个神经网络模型&#xff…

ORCA优化器浅析——ORCA core流程

DXL query messages is parsed and transformed to an in-memory logical expression tree that is copied-in to the MemoExploration 触发生成逻辑等价表达式的转换规则。探索阶段将新的群组表达式添加到现有组中&#xff0c;并可能创建新的组。Exploration results in addin…

Java性能优化-测试try-catch放在循环内和外的性能对比与业务区别

场景 Java中使用JMH(Java Microbenchmark Harness 微基准测试框架)进行性能测试和优化&#xff1a; Java中使用JMH(Java Microbenchmark Harness 微基准测试框架)进行性能测试和优化_霸道流氓气质的博客-CSDN博客 使用如上方式测试Java中try-catch放在循环内和循环外是否有性…

NiuBi!简单且匿名的密码喷洒工具

工具介绍 通过 Amazon AWS 直通代理启动密码喷洒/暴力破解&#xff0c;为每次身份验证尝试转移请求的 IP 地址。这会动态创建 FireProx API&#xff0c;以实现更规避的密码喷射。 关注【Hack分享吧】公众号&#xff0c;回复关键字【230525】获取下载链接 小心帐户锁定&#xf…

Java 设计模式——工厂方法模式

目录 1.案例分析2.简单工厂模式2.1.结构2.2.案例实现2.2.1.抽象产品2.2.2.具体产品2.2.3.具体工厂2.2.4.测试 2.3.优缺点2.4.扩展 3.✨工厂方法模式3.1.介绍3.1.结构3.2.案例实现3.2.1.抽象工厂3.2.2.具体工厂3.2.3.测试 3.3.优缺点3.4.应用场景 1.案例分析 【需求】设计一个咖…

python获取职教云信息

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;项目。 目录 1、需求1.1、推荐课程1.2、课程详情 2、思路分析2.1、推荐课程完整代码 2.2、课程详情找到JSON数据…

4.2.tensorRT基础(1)-第一个trt程序,实现模型编译的过程

目录 前言1. hello案例2. 补充知识总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 基础-第一个 trt 程序&#x…

SlickGrid学习

options&#xff1a; 选项 设置 enableCellNavigation 启用单元格导航&#xff0c;可以点单元格 enableColumnReorder 启动拖拽列 example-colspan.html 跨列实例 AutoTooltips plugin 隐藏列文字时自动显现列标题全文 Checkbox row select column 增加选择列来选择行…

STM32入门学习之core_cm3问题

1.安装了keil之后&#xff0c;新建工程出现几百个关于core_cm3的问题&#xff0c;百思不得其解。后在网上查阅资料后&#xff0c;了解到可能是keil版本的问题&#xff0c;是因为我下载的keill版本太高了&#xff0c;内部不支持ARM5.06的编译器。出现很多关于core_cm3的问题是因…

使用java语言制作一个窗体(弹窗),用来收集用户输入的内容

前言 最近做的一个需求&#xff0c;有个逻辑环节是&#xff1a;需要从本地保存的xml文件中取出一个值&#xff0c;这个值是会变化的。然后项目经理就给我说&#xff0c;你能不能做一个小工具&#xff0c;让用户可以直接通过界面化操作将这个变化的值写入文件&#xff0c;不用再…

rv1126交叉编译

目录 一、解压sdk二、交叉编译出动态库sqlite3交叉编译opencv交叉编译一、解压sdk tar xzvf rv1126_rv1109_linux_sdk_v1.8.0_PureVersion.tar.gz 查看交叉编译工具链 pwd查看绝对路径/home

正斜杠“/” 和反斜杠 “\” 傻傻分不清?

Note, on your keyboard, the location of two different punctuation marks—/, or forward slash, and \, or backward slash (also known as backslash). As you read from left to right, the forward slash falls forward while the backslash falls backward; 引用自 《…

js逆向思路-区分各个瑞数版本vmp/3/4/5/6代

目录 一、如何区分是最新瑞数vmp反爬二、3/4/5/6代/vmp版本的瑞数网站特征举例三、瑞数反爬的解决思路四、推荐相关瑞数文章五、一些心得一、如何区分是最新瑞数vmp反爬 前言:本篇文章不会介绍详细的解决反爬的算法扣代码过程,只是一些经验闲谈,文章的末尾有相关的好的质量的…

油猴脚本-Bilibili剧场模式仿Youtube

对比某个不存在的视频网站&#xff08;YouTube&#xff09;&#xff0c;以及B站的播放模式&#xff0c;普通模式以及网页全屏之间都有一个“中间档”&#xff0c;油管的叫 剧场模式&#xff0c;B站的叫 宽屏模式。 剧场模式 宽屏模式 相比之下&#xff0c;还是更喜欢油管的剧…

10.带你入门matlab频率表、盒图(matlab程序)

1.简述 相关概念介绍 以信号为例&#xff0c;信号在时域下的图形可以显示信号如何随着时间变化&#xff0c;而信号在频域下的图形&#xff08;一般称为频谱&#xff09;可以显示信号分布在哪些频率及其比例。频域的表示法除了有各个频率下的大小外&#xff0c;也会有各个频率的…