CS144 lab0 实现

假定你已经安装他的要求装好了vm。

Fetch a Web page

使用telnet请求网页

  1. telnet cs144.keithw.org http这条命令是启动telnet程序在你自己电脑和服务器之间建立一条可靠的数据流,同时运行一条特殊的服务(http)
  2. 接下来的几条操作需要手速快一点,输入GET /hello HTTP/1.1这条是告诉服务器你要访问的路径
  3. Host: cs144.keithw.org是告知主机url部分
  4. 接下来是Connection: close是通知服务器已经完成了请求,当完成转发后会关闭连接
  5. 多敲几次回车
    如果操作正确手速够快,那么结果如下
    image
    如果显示HTTP/1.1 408 Request Timeout那么说明你2345这几条命令输入不完全或者太慢了

Send yourself an email

因为实验设置是和Stanford的服务器进行交互,所以我们只能尝试和自己的邮箱交互.
以qq邮箱为例,需要使用IMAP/SMTP服务以及授权码

  1. telent smtp.qq.com smtp开启smtp服务(smtp是一个简单的邮件传输协议,主要用于发邮件)
    image
    2.helo qq.com给服务器打个招呼
    image
    3.接下来需要登录,输入auth login,之后收到334 VXNlcm5hbWU6字符,需要输入用户名(即你的qq邮箱),这里需要注意的是邮箱必须是转换为base64格式的,输入你的base64邮箱即可。
    如果没有问题那么会受到334 UGFzc3dvcmQ6提示,即输入授权码,将得到的授权码转换为base64格式输入即可。
    image
    4.接下来输入你的发送邮箱MAIL FROM: <xx@qq.com>
    5.接收者邮箱RCPT TO: <xx@gmail.com>
    6.输入DATA告诉服务器你要开始发送内容信息了,如果没有问题则会看到354 End data with <CR><LF>.</LF></CR>的消息
    7.输入headers信息和邮箱内容
    image
    记得以.表示结尾
    8.输入QUIT表示和email服务器会话结束

Listening and connecting

接下来玩一玩监听服务器
1.在一个窗口中使用netcat -v -l -p 9090启动监听程序
image
2.在另外一个窗口使用telnet localhost 9090连接该端口
3.如果成功,那么会显示Connection from localhost 56362 received!
4.现在可以在telnet的端口中输入一些字符,另一边可以看到接受的字符
image

Writing webget

主要用到了TCPSocket类Address类
TCPSocket中示例代码,演示了connect(const Address &address)write (const std::string &str, const bool write_all=true)方法的使用。
connect连接远程服务器,同时write发送get请求。
需要注意的是需要shutdown关闭对话,通过read()方法接受服务器的内容直到eof文件终止.

void get_URL(const string &host, const string &path) {

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

    cerr << "Function called: get_URL(" << host << ", " << path << ").\n";
    cerr << "Warning: get_URL() has not been implemented yet.\n";
}

An in-memory reliable byte stream

参考了大佬的博客的大部分代码,需要注意的点是每次修改完代码记得make编译一遍,再跑make check_lab0

题目要求你实现一个buffer,要求写入和读入在不同一侧,同时buffer有自己的容量限制。

 private:
    // Your code here -- add private members as necessary.
    std::deque<char> _bytestream = {};
    size_t _capacity = 0;
    size_t _bytes_written_number = 0;
    size_t _bytes_read_number = 0;
    bool _is_end = false;
    // 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.

    bool _error = false;  //!< Flag indicating that the stream suffered an error.
#include "byte_stream.hh"

// Dummy implementation of a flow-controlled in-memory byte stream.

// For Lab 0, please replace with a real implementation that passes the
// automated checks run by `make check_lab0`.

// You will need to add private members to the class declaration in `byte_stream.hh`

template <typename... Targs>
void DUMMY_CODE(Targs &&... /* unused */) {}

using namespace std;

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

size_t ByteStream::write(const string &data) {
    size_t len = data.length();
    if (len + _bytestream.size() > _capacity) {
        len = _capacity - _bytestream.size();
    }
    _bytes_written_number += len;
    for (size_t count = 0; count < len; count++) {
        _bytestream.push_back(data[count]);
    }
    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 process_len = len;
   if (process_len > _bytestream.size()) {
        process_len = _bytestream.size();
   }
   return string().assign(_bytestream.begin(), _bytestream.begin() + process_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 process_len = len;
   if (process_len > _bytestream.size()) {
        process_len = _bytestream.size();
   }
   _bytes_read_number += process_len;
   while (process_len--) {
        _bytestream.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 output = peek_output(len);
    pop_output(len);
    return output;
}

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

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

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

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

bool ByteStream::eof() const { return buffer_empty() and _is_end; }

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

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

size_t ByteStream::remaining_capacity() const {
    return _capacity - _bytestream.size();
}
posted @ 2021-09-01 18:44  lizhi334  阅读(1119)  评论(0编辑  收藏  举报