Lab Checkpoint 0: networking warmup
Lab 0 代码在 master 分支上
Related Links¶
2. Networking by hand¶
telnet cs144.keithw.org http
GET /hello HTTP/1.1
Host: cs144.keithw.org
Connection: close
心累…… 一开始一直获取不到,以为是网络的问题,然后自己搭建了一个 http 服务,结果还是不行。 然后再读了一遍文档,发现最后要输入一个空行…… 读文档要仔细啊!
3. Writing a network program using an OS stream socket¶
Commands
make
./apps/webget cs144.keithw.org /hello
make check_webget
通过查看文档中 TCPSocket Class 的用法,可以写出下面的代码。
void get_URL(const string &host, const string &path) {
TCPSocket socket;
socket.connect(Address(host, "http"));
socket.write("GET " + path + " HTTP/1.1\r\n");
socket.write("Host: " + host + "\r\n");
socket.write("Connection: close\r\n");
socket.write("\r\n");
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";
}
4. An in-memory reliable byte stream¶
Commands
make
make check_lab0
deque 来实现,因为方便实现 peek 操作(读取前 n 个字符)。按照代码注释和文档实现功能即可,难度不大。代码如下:
byte_stream.hh
#include <string>
#include <deque>
class ByteStream {
private:
std::deque<char> _myqueue;
size_t _capacity;
bool _input_ended;
size_t _bytes_written;
size_t _bytes_read;
bool _error{}; //!< Flag indicating that the stream suffered an error.
public:
// some codes...
}
byte_stream.cc
#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): _myqueue({}), _capacity(capacity), _input_ended(false), _bytes_written(0), _bytes_read(0) { }
size_t ByteStream::write(const string &data) {
const size_t len = data.length();
size_t res = 0;
for (size_t i = 0; i < len; i++) {
if (_myqueue.size() < _capacity) {
_myqueue.push_back(data[i]);
res++;
_bytes_written++;
}
else {
break;
}
}
return res;
}
//! \param[in] len bytes will be copied from the output side of the buffer
string ByteStream::peek_output(const size_t len) const {
string res;
size_t realPeekLen = len;
if (_myqueue.size() < realPeekLen) {
realPeekLen = _myqueue.size();
}
res.assign(_myqueue.begin(), _myqueue.begin() + realPeekLen);
return res;
}
//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {
size_t realPopLen = len;
if (_myqueue.size() < realPopLen) {
realPopLen = _myqueue.size();
}
_bytes_read += realPopLen;
for (size_t i = 0; i < realPopLen; i++) {
_myqueue.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 res = peek_output(len);
pop_output(len);
return res;
}
void ByteStream::end_input() { _input_ended = true; }
bool ByteStream::input_ended() const { return _input_ended; }
size_t ByteStream::buffer_size() const { return _myqueue.size(); }
bool ByteStream::buffer_empty() const { return _myqueue.size() == 0; }
bool ByteStream::eof() const {
if (_input_ended && _myqueue.size() == 0) {
return true;
}
else {
return false;
}
}
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 - _myqueue.size(); }




