遵循一些代码的守则:
- 不用 malloc() free() new delete
- 不用空指针和智能指针
- 不用模板,线程,锁,虚函数
- 不用c风格的字符串,直接用cpp的string
- 不要使用c风格的强制转换,使用cpp的 static_cast(在cs144中不太会用到)
- 最好使用常量引用去传递函数的参数
- 不会改变的变量设为常量
- 不会改变内容的函数,设为const函数
- 避免使用全局变量,尽量使得每个变量的作用域最小
- 提交之前,通过 **make format ** 去检查代码风格。
Part 1
Lab 0非常简单,就是模仿telnet,向server发请求,然后把返回的信息打印出来。
主要这边就是先熟悉一下 FileDescriptor、Socket、Address三个类,当然不熟悉也可以直接仿照 socket_example_2.cc去实现。
其中没有看懂 Socket 和 Address 是怎么联系起来的,而且它里面很多都是系统调用。
直接贴代码
void get_URL(const string &host, const string &path) {
TCPSocket sock1;
sock1.connect(Address(host, "http"));
string request = "GET "+ path + " HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n";
string str;
sock1.write(request);
while(!sock1.eof()){
cout<<sock1.read();
}
sock1.close(); // 记得关闭socket,不然检测会b
}
Part 2
第二部分是写一个在内存中的可信赖字节流。就是类似于buffer的东西,提供了接口形式去实现就行了。总体上不难,但是需要去理解给的接口的作用,这个是在调试的时候可以比较好的理解。
我这边实现的主体思路就是循环队列。
直接贴代码了,然后说几点遇到的问题。
- num_of_read是取决于 pop_output 而不是 read
- end_input_flag 需要主动调用函数end_input() 去修改,而不是在write 未写完的情况下去修改
// part of byte_stream.hh
// 主要就是增加了几个成员
private:
// Your code here -- add private members as necessary.
// 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.
std::string buf{};
size_t start{},end{},cap{};
size_t num_of_write{},num_of_read{};
bool end_input_flag{};
bool _error{}; //!< Flag indicating that the stream suffered an error.
// byte_stream.cc
using namespace std;
ByteStream::ByteStream(const size_t capacity) {
cap = capacity + 1;
buf.resize(capacity + 1);
start = 0;
// the case that (end + 1) mod cap == start represents there is no info in buf
end = capacity;
num_of_write = num_of_read = 0;
end_input_flag = false;
_error = false;
}
size_t ByteStream::write(const string &data) {
size_t ret = 0;
ret = min(remaining_capacity(),data.size());
for(int i = 0,limit = static_cast<int>(ret);i < limit;i++){
end = (end + 1) % cap;
buf[end] = data[i];
}
// if write is not end,modify the flag
num_of_write += ret;
end_input_flag = false;
return ret;
}
//! \param[in] len bytes will be copied from the output side of the buffer
string ByteStream::peek_output(const size_t len) const {
string ret;
ret.resize(len);
for(int i = 0,limit = static_cast<int> (len);i < limit;i++){
ret[i] = buf[(start + i) % cap];
}
return ret;
}
//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {
start = (start + len) % cap;
num_of_read += len;
}
//! 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) {
size_t sz = min(buffer_size(),len);
printf("sz : %d\n",static_cast<int> (sz));
string ret = peek_output(sz);
pop_output(sz);
return ret;
}
void ByteStream::end_input() { end_input_flag = true; }
bool ByteStream::input_ended() const { return end_input_flag; }
size_t ByteStream::buffer_size() const { return cap - remaining_capacity() - 1; }
bool ByteStream::buffer_empty() const {
return buffer_size() == 0; }
bool ByteStream::eof() const { return input_ended() && buffer_empty(); }
size_t ByteStream::bytes_written() const { return num_of_write; }
size_t ByteStream::bytes_read() const {return num_of_read;}
size_t ByteStream::remaining_capacity() const {
size_t e = end,s = start;
if((e + 1)%cap == s)
return cap - 1;
if(s <= e)
s += cap;
return s - e - 2;
}
不知道为啥 make format用不了~
还有就是不知道为啥有时候 test 6会失败
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN2XjlGcjcmbw5iYxYWYwE2Y0AzM2kzMmFDNxcDMiBjN0kjYzYzN3MjZ38CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)