代码见github:cs144_lab
lab0
- Modern C++: mostly safe but still fast and low-leve:给出了一些建议与规范。
- 要理解: a
Socket
is a type ofFileDescriptor
, and aTCPSocket
is a type ofSocket
。
webget
util的类图
实现
void get_URL( const string& host, const string& path )
{
TCPSocket sock;
sock.connect(Address(host, "http"));
string data_send = "GET " + path + " HTTP/1.1\r\nHost: " + host + "\r\n" + "Connection: close\r\n\r\n";
sock.write(data_send);
while (!sock.eof()) {
std::string data_recv;
sock.read(data_recv);
std::cout << data_recv;
}
sock.close();
}
问题
- 如果加上
std::cout << std::endl;
会测试通不过
改进
an in-memory reliable byte stream
实现
这里使用deque
,本来使用了queue
,但是不能使用迭代器,就不能peek
。
还有人使用string
加双指针来实现
两个文件:
byte_stream.hh
#pragma once
#include <queue>
#include <stdexcept>
#include <string>
#include <string_view>
class Reader;
class Writer;
class ByteStream
{
protected:
uint64_t _capacity;
std::deque<char> _queue;
uint64_t _writen_size;
uint64_t _read_size;
bool _end_input;
bool _error;
// Please add any additional state to the ByteStream here, and not to the Writer and Reader interfaces.
public:
explicit ByteStream( uint64_t capacity );
// Helper functions (provided) to access the ByteStream's Reader and Writer interfaces
Reader& reader();
const Reader& reader() const;
Writer& writer();
const Writer& writer() const;
};
class Writer : public ByteStream
{
public:
void push( std::string data ); // Push data to stream, but only as much as available capacity allows.
void close(); // Signal that the stream has reached its ending. Nothing more will be written.
void set_error(); // Signal that the stream suffered an error.
bool is_closed() const; // Has the stream been closed?
uint64_t available_capacity() const; // How many bytes can be pushed to the stream right now?
uint64_t bytes_pushed() const; // Total number of bytes cumulatively pushed to the stream
};
class Reader : public ByteStream
{
public:
std::string peek() const; // Peek at the next bytes in the buffer
void pop( uint64_t len ); // Remove `len` bytes from the buffer
bool is_finished() const; // Is the stream finished (closed and fully popped)?
bool has_error() const; // Has the stream had an error?
uint64_t bytes_buffered() const; // Number of bytes currently buffered (pushed and not popped)
uint64_t bytes_popped() const; // Total number of bytes cumulatively popped from stream
};
/*
* read: A (provided) helper function thats peeks and pops up to `len` bytes
* from a ByteStream Reader into a string;
*/
void read( Reader& reader, uint64_t len, std::string& out );
byte_stream.cc
#include <stdexcept>
#include "byte_stream.hh"
using namespace std;
ByteStream::ByteStream( uint64_t capacity ) : _capacity( capacity ),_queue(),_writen_size(0),_read_size(0),_end_input(false),_error(false) {}
void Writer::push( string data )
{
if(_end_input) return;
uint64_t push_size = min(data.size(), available_capacity()); //这里截断输入
for(uint64_t i = 0; i < push_size; i++)
{
_queue.push_back(data[i]);
}
_writen_size += push_size;
}
void Writer::close(){ _end_input = true;}
void Writer::set_error(){_error = true;}
bool Writer::is_closed() const {return _end_input;}
uint64_t Writer::available_capacity() const
{
uint64_t a_c = _capacity - _queue.size();
return a_c;
}
uint64_t Writer::bytes_pushed() const{return _writen_size;}
string Reader::peek() const{return string(_queue.begin(),_queue.end()); //支持迭代器}
bool Reader::is_finished() const{return (_end_input && (_queue.size() == 0));}
bool Reader::has_error() const{return _error;}
void Reader::pop( uint64_t len )
{
uint64_t pop_size = min(len, _queue.size());
_read_size += pop_size;
while(pop_size--)
{
_queue.pop_front();
}
}
uint64_t Reader::bytes_buffered() const{return _queue.size();}
uint64_t Reader::bytes_popped() const{return _read_size;}
运行结果:
问题
- 速度测试失败了,不知道是不是我用的虚拟机的性能问题,换个机器试一试。
- 在本来提供的代码框架里使用了
string_view
的特性,但是我的不正确使用导致栈溢出:
std::string_view peek() const; // Peek at the next bytes in the buffer
为了方便我使用了string
替代:
std::string peek() const; // Peek at the next bytes in the buffer
改进
- 使用
string_view
- 提速
调试
主要是在vscode调试tests
中测试代码。配置launch.json
:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "test debug",
"type": "cppdbg",
"request": "launch", //launch和attach区别
"program": "${workspaceFolder}/build/tests/${fileBasenameNoExtension}", //调试程序的目录
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}", //json所在文件夹的位置
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}
选中源文件,这样就能在debug插件一键启动调试二进制文件了。