前言

感觉学了不少 C++ 编程的知识和技术但比较缺少实践,于是打算找一些项目跟着做一做。
首先安利一个自学网站 CS自学指南,北大的同学做的,汇总了很多国内外高校 CS 相关的高质量公开课,其中大部分是有课程项目的。翻了翻感觉 Stanford 的这门 CS144 计网课的 Lab 比较有趣,难度也不错,就是它了!

课程网址:CS 144: Introduction to Computer Networking
我跟的是 2021 Fall 学期的版本。

我的 Github 项目:CS144-Lab,7个实验的完成版代码位于 libsponge/ 文件夹内。

准备工作


在上面的网站中先把 8 个实验的文档(红框)下载下来,然后按上图中 Virtual machine setup instructions 链接开始设置虚拟机环境。推荐使用方法一:VirtualBox + 课程组准备好的 Ubuntu 镜像,跟着这个链接的步骤做就可以。设置共享文件夹那步建议完成。

完成后得到的是一个控制台界面的 Ubuntu 18.04 系统。该虚拟机已经设置好可以通过ssh连接(localhost:2222 端口),为了方便开发,可以用 PuTTY 连接打开多个窗口,配置如下(建议保存成 session,每次直接加载):


因为没有图形界面,开发工具自然是用 Vim,如果对 Vim 操作不熟练(比如博主自己ww)正好是个不错的锻炼机会。如果完全没有接触过 Vim,可以看 MIT 的 Missing Semester 中 Editors (Vim) 这课入门。关于 Vim 环境的配置,个人还是比较建议装一些插件(如语法高亮、代码补全等)改善开发体验,我的 .vimrc 如下,主要使用了 Vundle 插件管理,Molokai 主题,YouCompleteMe 代码分析补全还有 Vim 自带的显示行号等基本功能。Vim 的很多插件可以在这个网站上淘到。如果有需要以后也可以写一篇文章记录这个配置过程。

Lab 0

因为计网的知识大三都学过,做完以上准备工作就可以愉快地开始实验了。Lab 0 的第二部分 Networking by hand 和第三部分 Writing a network program using an OS stream socket 都比较简单,跟着文档说明一步步做就好,这里直接看第四部分 An in-memory reliable byte stream。

本节要求我们实现一个可靠的字节流(Byte Stream)类,reader/writer 分别能够从一端读出数据,一端写入数据,同时要控制流中数据任意时刻不能超过某个容量(capacity)值。这里无需考虑多线程使用读写锁等问题。需要实现的 public 函数已经定义好,实现时可以补充任意私有成员。

待完成的代码在 sponge/libsponge 目录内,完成后在 sponge/build 目录中执行 make (-j4/-j8) 编译,然后执行 make check_lab0 以运行自动测试,如果看到 100% tests Passed 则说明通过(t_webget 需要连接国外网站,耗时较长或超时都没关系)。如果需要运行单个测试,执行 ctest -R 测试名,测试名就是运行所有测试时输出的 Test #1: t_xx 中的 t_xx,然后根据提示信息可以查看单次测试的输出日志(注意:如果要用打印语句 Debug,用 cerr 而不是 cout 输出)。以后的实验都是如此,不再重复。

回到本次任务,要求还是比较简单的,选用一个数据结构存储数据流并维护一些状态信息即可,我这里用的是 deque<char>。容器的操作等实现细节上注意尽量用 Modern C++ 的风格。

ByteStream.hh:

#ifndef SPONGE_LIBSPONGE_BYTE_STREAM_HH
#define SPONGE_LIBSPONGE_BYTE_STREAM_HH#include <deque>
#include <string>//! \brief An in-order byte stream.//! Bytes are written on the "input" side and read from the "output"
//! side.  The byte stream is finite: the writer can end the input,
//! and then no more bytes can be written.
class ByteStream {private:// Your code here -- add private members as necessary.// Hint: This doesn't need to be a sophisticated data structure at// all, but if any of your tests are taking longer than a second,// that's a sign that you probably want to keep exploring// different approaches.std::deque<char> _buf{};std::size_t _capacity;std::size_t _bytes_written = 0;std::size_t _bytes_read = 0;bool _input_ended = false;bool _error = false;  //!< Flag indicating that the stream suffered an error.public://! Construct a stream with room for `capacity` bytes.ByteStream(const size_t capacity);//! \name "Input" interface for the writer//!@{//! Write a string of bytes into the stream. Write as many//! as will fit, and return how many were written.//! \returns the number of bytes accepted into the streamsize_t write(const std::string &data);//! \returns the number of additional bytes that the stream has space forsize_t remaining_capacity() const;//! Signal that the byte stream has reached its endingvoid end_input();//! Indicate that the stream suffered an error.void set_error() { _error = true; }//!@}//! \name "Output" interface for the reader//!@{//! Peek at next "len" bytes of the stream//! \returns a stringstd::string peek_output(const size_t len) const;//! Remove bytes from the buffervoid pop_output(const size_t len);//! Read (i.e., copy and then pop) the next "len" bytes of the stream//! \returns a stringstd::string read(const size_t len);//! \returns `true` if the stream input has endedbool input_ended() const;//! \returns `true` if the stream has suffered an errorbool error() const { return _error; }//! \returns the maximum amount that can currently be read from the streamsize_t buffer_size() const;//! \returns `true` if the buffer is emptybool buffer_empty() const;//! \returns `true` if the output has reached the endingbool eof() const;//!@}//! \name General accounting//!@{//! Total number of bytes writtensize_t bytes_written() const;//! Total number of bytes poppedsize_t bytes_read() const;//!@}
};#endif  // SPONGE_LIBSPONGE_BYTE_STREAM_HH

ByteStream.cc:

#include "byte_stream.hh"using namespace std;ByteStream::ByteStream(const size_t capacity) : _capacity(capacity) {}size_t ByteStream::write(const string &data) {if (_input_ended) {return 0;}size_t write_len = min(data.size(), remaining_capacity());_buf.insert(_buf.end(), data.begin(), data.begin() + write_len);_bytes_written += write_len;return write_len;
}//! \param[in] len bytes will be copied from the output side of the buffer
string ByteStream::peek_output(const size_t len) const {size_t peeked_len = min(len, _buf.size());return string(_buf.begin(), _buf.begin() + peeked_len);
}//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {size_t popped_len = min(len, _buf.size());_buf.erase(_buf.begin(), _buf.begin() + popped_len);_bytes_read += popped_len;
}//! Read (i.e., copy and then pop) the next "len" bytes of the stream
//! \param[in] len bytes will be popped and returned
//! \returns a string
string ByteStream::read(const size_t len) {if (len == 0) {return "";}string res = peek_output(len);pop_output(res.size());return res;
}void ByteStream::end_input() { _input_ended = true; }bool ByteStream::input_ended() const { return _input_ended; }size_t ByteStream::buffer_size() const { return _buf.size(); }bool ByteStream::buffer_empty() const { return _buf.empty(); }bool ByteStream::eof() const { return input_ended() && buffer_empty(); }size_t ByteStream::bytes_written() const { return _bytes_written; }size_t ByteStream::bytes_read() const { return _bytes_read; }size_t ByteStream::remaining_capacity() const { return _capacity - _buf.size(); }

最后贴张通关图

【斯坦福计网CS144项目】环境配置 Lab0: ByteStream相关推荐

  1. Vue第七章:项目环境配置及单文件组件 vue脚手

    第七章:项目环境配置及单文件组件 vue脚手架 回顾: 组件之间的通信 父传子:正向传递 vue允许 自动触发 ​ props ​ 1.先在子组件中定义期待的属性名和类型 ​ 2.在父组件中调用子组件 ...

  2. 【java】项目环境配置

    项目环境配置 一.SVN 版本控制 1. 下载安装 2. Checkout同步代码 3. Update更新代码 4. Commit提交代码 5. 撤销本地修改 6. 查看提交记录 二.IntellJ ...

  3. 【持续集成和交付】项目环境配置:在Jenkins中运行项目

    前言 一直想学习自动化测试,但是都没行动,业余时间学习零零碎碎并记录20210424. 11.持续集成和交付 Jenkins环境搭建 项目环境配置 邮件通知 定时项目执行 在Jenkins中运行项目 ...

  4. Python人脸识别项目-环境配置

    环境配置 首先我们需要需要配置所需的环境,作者使用的编译器是Pycharm,在安装失败多次情况下(不知道为什么我Pycharm上装有问题),我发现了最简单的配置方法.首先在工作台中输入以下命令进行安装 ...

  5. Vue项目环境配置(尚硅谷笔记)

    文章目录 Vue3项目继承 一.项目集成 3.1集成element-plus 3.2src别名的配置 3.3环境变量的配置 3.4SVG图标配置 3.4.1svg封装为全局组件 3.5集成sass 3 ...

  6. java的jdk安装教程附百度网盘链接环境配置遇到的各种问题版本选择

    首先关于JDK版本的选择–附百度网盘链接 现在互联网行业各家公司大部分使用的是jdk8.0(也被叫做jdk1.8,有兴趣的话可以去百度以下jdk演变历史)虽然现在jdk更新到11版本了,但是不建议使用 ...

  7. 【SLAM】——DynaSLAM项目环境配置(超多坑)

    DynaSLAM 坑多,慢慢来,不要急 先整体说一下,项目是在ORB-SLAM2项目的基础上,加上maskrcnn的融合.主流程采用还是采用ORB-SLAM2的流程,maskrcnn部分采用c++调用 ...

  8. 前端——vue项目环境配置

    node类似一个浏览器,npm是包管理器. 搞node的开发者不想维护node了,所以把node交给了好友npm开发者,这个npm开发者就把两个搞一起去了.. 我们配置java环境的流程是下载jdk, ...

  9. vscode安装使用,开发python项目环境配置

    # 一.vscode设置python解释器 1.使用vscode添加需要的插件在扩展商店汉化chinese进行python开发python 完成汉化以及提示补全django用到的Git history ...

最新文章

  1. 为了鉴别世界名画,我死磕CNN后终于搭建了自己的模型
  2. 二叉树的概念、算法简介及树的平衡
  3. 【javascript 对日期的扩展 Format\addDays】
  4. 黑马程序员 Python学习笔记之 程序执行原理(科普)
  5. IPQ4019 QSDK 下添加RM500Q 5G 驱动 qmi拨号链接网络 配置 IPK包方法
  6. Terminal终端命令(全)
  7. 咸鱼笔记:《实用软件工程》第一、二章课后简答题及参考答案
  8. 开机bat脚本解决steam无法自动登陆
  9. android黑科技系列——手机端破解神器MT的内购VIP功能破解教程
  10. 《现代汉语》北大公开课
  11. python土味情话_GitHub - MMstarry/itchat: 微信机器人 土味情话
  12. 枚举证书和 CAPI读取证书总结
  13. 搜狗输入法 - 自定义短语
  14. MATLAB函数大全 .
  15. 装饰模式 - Unity
  16. Ubuntu定时开关机
  17. ysdk接入,支付提示:系统繁忙,请稍后再试 (1003-498686-498686)
  18. Android官网教你如何系统学习
  19. service饬令用于经管Linux把持系统中效劳的饬令
  20. 读《区块链革命 》有感

热门文章

  1. Multisim14 安装包及安装教程
  2. 使用ArcGIS进行拓扑检查
  3. NRS1800 芯片使用技巧(一)
  4. android Studio 下载问题
  5. c++ 遍历文件夹下的所有文件
  6. 基于java大学生就业招聘系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
  7. python有中文版吗-python有中文版
  8. golang编程cobra-cli库使用
  9. C/C++ 算法设计与分析实验报告
  10. Python:实现多个txt文本的简单合并,亲测简单好用,保姆教程