最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

【计算机网络】Stanford CS144 Lab0 : networking warmup 学习记录

来源:博客园

CS144 官方镜像 : https://cs144.github.io/kangyupl备份的镜像 : https://kangyupl.gitee.io/cs144.github.io/


(资料图)

实验准备

  • Ubuntu 18.04.6 LTS x86_64 (实验提供)
  • gcc8 或 clang6 (实验机提供的gcc是7.5, 没有达到实验文档要求)

Writing webget

要求使用 TCPSocketAddress来抓取网页内容。

TCP 套接字编程,实验已经使用 C++ 封装好了 TCPSocket

建立 TCPSocket, 并向目标主机的 80号端口建立 TCP 连接。

发送 HTTP 请求报文。

HTTP 报文格式

GET /somedir/page.html HTTP/1.1\r\nHost: www.someschool.edu\r\nConnection: close\r\nUser-agent: Mozilla/5.0\r\nAccept-language: fr\r\n\r\n

发送完报文,使用 shutdown(SHUT_WR)表示请求发送完了。

之后使用 read()读取目标主机返回的报文即可。

TCPSocket sock{};sock.connect(Address{host, "http"});sock.write("GET " + path + " HTTP/1.1\r\nHost: " + host + "\r\n\r\n");sock.shutdown(SHUT_WR);while (!sock.eof()) {    cout << sock.read();}sock.close();

An in-memory reliable byte stream

在内存中实现一个可靠的字节流对象,可以按照写的顺序读出数据。这个字节流是可以边写边读的。字节流读的操作会把数据从数据结构头部位置开始 pop数据,写的操作会从数据结构的尾部 push数据,因此我们考虑使用 std::deque来实现。

为什么不使用 std::queue?

读的操作分为了两步,第一步是从读取长度为 len的字节流,第二步是将这长度为 len的字节流从数据结构中删除。

这两个操作分为了两个函数。对于第一个函数,我们需要一个 iterator来选取要取出的字节范围,而 std::queue没有提供一个 iterator接口。

当然,也可以使用 std::list来实现这个数据结构。

byte_stream.hh

class ByteStream {  private:    std::deque _buffer{};    size_t _capacity = 0;    size_t _write_cnt = 0;    size_t _pop_cnt = 0;    bool _stream_end = false;    bool _error = false;     ...

构造函数

ByteStream::ByteStream(const size_t capacity) : _capacity{capacity} {}

写的操作,因为我们的 _buffer是有容量限制的,因此要判断要写入的是否超过了容量。

size_t ByteStream::write(const string &data) {    const size_t res = std::min(data.size(), _capacity - _buffer.size());    _write_cnt += res;    for (size_t i = 0; i < res; i++) {        _buffer.push_back(data[i]);    }    return res;}

读的操作,先 peek_outputpop_output

string ByteStream::peek_output(const size_t len) const {    const size_t peek_len = std::min(len, _buffer.size());    return std::string{}.assign(_buffer.begin(), _buffer.begin() + peek_len);}
void ByteStream::pop_output(const size_t len) {    const size_t pop_len = std::min(len, _buffer.size());    _pop_cnt += pop_len;    for (size_t i = 0; i < pop_len; i++) {        _buffer.pop_front();    }    return;}
// 输入结束,由使用者调用void ByteStream::end_input() { _stream_end = true; }// `true` 表示 输入结束bool ByteStream::input_ended() const { return _stream_end; }// buffer 现在有多少字节size_t ByteStream::buffer_size() const { return _buffer.size(); }// `true` 表示 buffer 是空的bool ByteStream::buffer_empty() const { return _buffer.empty(); }// ‘true’ 表示 读 完了数据bool ByteStream::eof() const { return buffer_empty() && input_ended(); }// 写入了多少字节,写入时累积size_t ByteStream::bytes_written() const { return _write_cnt; }// 弹出 buffer 的数据大小size_t ByteStream::bytes_read() const { return _pop_cnt; }// 目前空余的容量大小size_t ByteStream::remaining_capacity() const { return _capacity - _buffer.size(); }

关键词: 数据结构 计算机网络 因为我们