CS144-Lab0解析

讲在开头

cs144建议我们使用Modern C++来完成所有的lab,关于modern c++的全面的用法可以在(http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)获取。

以下是一些代码规范:

  • 不要使用malloc()free()
  • 不要使用newdelete
  • 在不得不使用指针时应使用智能指针(unique_ptr或者shared_ptr),而不是原始指针(*)
  • 避免使用模板、多线程、锁和虚函数
  • 避免使用C风格的类型转换(FILE)*x,必要时使用C++的static_cast
  • 避免使用C风格的字符串char *s,和C语言中的字符串函数strlen(), strcpy(),应使用c++中 std::string
  • 尽可能的使用常量引用(e.g.: const Address & address
  • 尽可能用const修饰变量和方法
  • 避免全局变量,尽可能缩小每个变量的作用域
  • 在提交之前,请使用make format来修改代码风格

在本次热身实验中,我们将会利用操作系统预先存在的接口来实现一个简单的TCP socket,并利用这个tcp socket来实现对网页的请求。

使用OS的流套接字写一个网络程序

这个部分比较简单,只需要按照handout所说,看完TCPSocketFileDescriptorSocketAddress这几个类的介绍,就能很快的完成这个程序,其实只需要看TCPSocket class就行。这些源代码都在libsponge\util中。

Inheritance graph

在linux系统中,一切皆文件。

webget.c

void get_URL(const string &host, const string &path) {
    TCPSocket tsk;
    tsk.connect(Address(host,"http"));

    tsk.write("GET " + path + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
                "Connection: close\r\n\r\n");
    string str;
    while(!tsk.eof()) {
        tsk.read(str);
        cout << str;
    }

    tsk.close();
}

注意的是write的字符串要写成HTTP请求的格式,这也就是我们的应用层数据,在通过socket后会封装上TCP头部再丢进网络层传输。

内存中的可靠数据流

我们要完成的任务是实现一个类似于管道的数据结构ByteStream,这个channel有两端,一端是input side,负责向channel中输入字符串,另一端是output side,负责从channel中读取字符串并且取出来,在抽象的数据结构中来看,std::deque双端队列最合适不过。

这个管道是有容量限制的,其在初始化时就会规定好其capacity,作为在任意时刻channel内的最大字符量。随着output side对channel内字符串的读取,input side被允许写入更多的字符串,这意味着ByteStream可以传输比其自身capacity更大的数据,换句话就是ByteStream的容量理论上可以达到无限,只要input side持续地write。

在对ByteStream的功能熟悉后,我们就可以在libsponge\byte_stream.hhlibsonge\byte_stream.cc的骨架代码中完成我们的实现。这里需要特别强调一下**EOF的状态:** end of file是指在input side终止了输入的前提下,output side从channel中读取完了所有的字符串,此时ByteStream中的数据为空,并且不会再有数据输入。

对于ByteStream类,我添加的私有成员如下:

class ByteStream {
  private:
    // Your code here -- add private members as necessary.
    size_t _capacity;
    bool _eof = false;
    std::deque<char> _buffer;
    size_t _total_write;
    size_t _total_read;
    

    bool _error{};  //!< Flag indicating that the stream suffered an error.

  ...
}

ByteStream类的方法的实现:

ByteStream::ByteStream(const size_t capa) : _capacity(capa), _eof(false), _buffer(), _total_write(0), _total_read(0) {}

size_t ByteStream::write(const string &data) {
    size_t remain_size = _capacity - _buffer.size();
    size_t len = min(remain_size, data.length());
    for (size_t i = 0; i < len; i++)
        _buffer.push_back(data[i]);
    _total_write += len;
    return 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 l = min(len, _buffer.size());
    string output = "";
    for (size_t i = 0; i < l; i++)
        output += _buffer[i];

    return output;
}

//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {
    size_t l = min(len, _buffer.size());
    _total_read += l;
    while (l--)
        _buffer.pop_front();
}

//! 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
std::string ByteStream::read(const size_t len) {
    string str = peek_output(len);
    pop_output(len);
    return str;
}

void ByteStream::end_input() { _eof = true; }

bool ByteStream::input_ended() const { return _eof; }

size_t ByteStream::buffer_size() const { return _buffer.size(); }

bool ByteStream::buffer_empty() const { return _buffer.empty(); }

bool ByteStream::eof() const { return _eof && _buffer.empty(); }

size_t ByteStream::bytes_written() const { return _total_write; }

size_t ByteStream::bytes_read() const { return _total_read; }

size_t ByteStream::remaining_capacity() const { return _capacity - _buffer.size(); }

通过下列指令完成编译;

mkdir build
cd build
cmake ..
make
make check_lab0

结果如下:

image-20221219011624614

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linengcs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值