CS144 lab0 实现
假定你已经安装他的要求装好了vm。
Fetch a Web page
使用telnet请求网页
telnet cs144.keithw.org http
这条命令是启动telnet程序在你自己电脑和服务器之间建立一条可靠的数据流,同时运行一条特殊的服务(http)- 接下来的几条操作需要手速快一点,输入
GET /hello HTTP/1.1
这条是告诉服务器你要访问的路径 Host: cs144.keithw.org
是告知主机url部分- 接下来是
Connection: close
是通知服务器已经完成了请求,当完成转发后会关闭连接 - 多敲几次
回车
如果操作正确手速够快,那么结果如下
如果显示HTTP/1.1 408 Request Timeout
那么说明你2345这几条命令输入不完全或者太慢了
Send yourself an email
因为实验设置是和Stanford的服务器进行交互,所以我们只能尝试和自己的邮箱交互.
以qq邮箱为例,需要使用IMAP/SMTP服务以及授权码
telent smtp.qq.com smtp
开启smtp服务(smtp是一个简单的邮件传输协议,主要用于发邮件)
2.helo qq.com
给服务器打个招呼
3.接下来需要登录,输入auth login
,之后收到334 VXNlcm5hbWU6
字符,需要输入用户名(即你的qq邮箱),这里需要注意的是邮箱必须是转换为base64格式的,输入你的base64邮箱即可。
如果没有问题那么会受到334 UGFzc3dvcmQ6
提示,即输入授权码,将得到的授权码转换为base64格式输入即可。
4.接下来输入你的发送邮箱MAIL FROM: <xx@qq.com>
5.接收者邮箱RCPT TO: <xx@gmail.com>
6.输入DATA
告诉服务器你要开始发送内容信息了,如果没有问题则会看到354 End data with <CR><LF>.</LF></CR>
的消息
7.输入headers信息和邮箱内容
记得以.
表示结尾
8.输入QUIT
表示和email服务器会话结束
Listening and connecting
接下来玩一玩监听服务器
1.在一个窗口中使用netcat -v -l -p 9090
启动监听程序
2.在另外一个窗口使用telnet localhost 9090
连接该端口
3.如果成功,那么会显示Connection from localhost 56362 received!
4.现在可以在telnet的端口中输入一些字符,另一边可以看到接受的字符
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();
}
Think twice~ Code once!