CS144 lab0(个人理解)

前言

Lab0 有两个任务,第一个任务是实现能发送 Get 请求到任意网址的 webget 程序(Writing webget ),第二个任务是实现内存内的可靠字节流(An in-memory reliable byte stream)。

任务1:Writing webget

基本原理

下列代码能在Linux 系统中实现对一个web进行请求并返回内容(输入要快,且最后一下要多按一次回车)

Linux_cmd 复制代码
telnet cs144.keithw.org http
GET /hello HTTP/1.1
Host: cs144.keithw.org
Connection: close

正常运行结果:

代码实现

该任务具体是要用代码实现在命令界面相同的结果

Socket可以认为是对一个文件进行读写操作。因此可以被抽象为一个文件描述符FileDescriptor,在源码中TCP Socket、UDP Socket等Socket类继承FileDescriptor类。

头文件:util/file_descriptor.hh

文件描述符是计算机操作系统中用于标识和访问打开的文件或设备的整数值。在 Linux 中,内核通过文件描述符来找到每个文件,一个文件可以被许多用户同时打开或一个用户同时打开多次,为管理文件的当前位移量等问题,引入了文件描述符。

具体实现在apps/webget.cc中需要补全void get_URL( const string& host, const string& path )

  • 先构建连接
C++ 复制代码
Address const myaddress(host,"http");//host为主机地址,http为连接方式
TCPSocket mysocket;
mysocket.connect(myaddress);
  • 构建并写入指令
C++ 复制代码
string const getcom = "GET "+path+" HTTP/1.1\r\n";
string const hostcom = "Host: "+host+"\r\n";
string const concom = "Connection: close\r\n\r\n";
mysocket.write(getcom);
mysocket.write(hostcom);
mysocket.write(concom);
  • 读取返回的数据
C++ 复制代码
while(!mysocket.eof()) {//eof为bool终止条件
  string buff="";
  mysocket.read(buff);
  cout<<buff;
}
mysocket.close();//关闭socket

总代码

C++ 复制代码
void get_URL( const string& host, const string& path )
{
  Address const myaddress(host,"http");
  TCPSocket mysocket;
  mysocket.connect(myaddress);

  string const getcom = "GET "+path+" HTTP/1.1\r\n";
  string const hostcom = "Host: "+host+"\r\n";
  string const concom = "Connection: close\r\n\r\n";
  mysocket.write(getcom);
  mysocket.write(hostcom);
  mysocket.write(concom);
  while(!mysocket.eof()) {
    string buff="";
    mysocket.read(buff);
    cout<<buff;
  }
  mysocket.close();

}

控制台输入(因为我是Clion ssh连接,所以路径不同)

Linux_cmd 复制代码
make
./apps/webget cs144.keithw.org /hello

下一步是通过测试案例,控制台输入 cmake --build build --target check webget

任务2:An in-memory reliable byte stream

实现一个可靠的字节流:

  • 字节在输入端写入,在输出端输出保持相同顺序读取(队列)
  • 可终止写入以及读取(EOF)
  • 能够处理大容量字节流

Writer类:

C++ 复制代码
void push( std::string data ); 
// 功能:将数据推送到流中(注意范围)

void close(); 
// 功能:发出信号表示流已到达结尾

bool is_closed() const; 
// 功能:判断流是否已经关闭

uint64_t available_capacity() const; 
// 功能:字节流可写入容量

uint64_t bytes_pushed() const; 
// 功能:查询累计推送到该流的字节总数是多少

Reader类:

C++ 复制代码
std::string_view peek() const; 
// 功能:查看缓冲区中的下一批字节内容,但并不移除它们
//(std::string_view类型,可用于查看字节数据而无需复制)

void pop( uint64_t len ); 
// 功能:从缓冲区中移除`len`个字节

bool is_finished() const; 
// 功能:判断流是否已经结束(即已关闭且所有数据都已被弹出)

bool has_error() const; 
// 功能:判断流是否出现过错误

uint64_t bytes_buffered() const; 
// 功能:查询当前在缓冲区中缓冲的字节数(即已推送但尚未弹出的字节数)

uint64_t bytes_popped() const; 
// 功能:查询累计从流中弹出的字节总数

byte_stream.hh

则在src/byte_stream.hh中可写入

C++ 复制代码
protected:
  // Please add any additional state to the ByteStream here, and not to the Writer and Reader interfaces.
  uint64_t capacity_;//流容量
  bool error_ {};
  //新增:
  std::string buffer_ {};//流缓存
  uint64_t bytes_pushed_ {};//写入字节
  uint64_t bytes_poped_ {};//读取字节
  bool isclosed_ {};//判断关闭
  • std::string buffer_ {};可视为整个字节流的写入以及读取的队列
  • uint64_t bytes_pushed_ {};用于统计总写入字节数
  • uint64_t bytes_poped_ {};用于统计总读取字节数
  • bool isclosed_ {};控制流的关闭

byte_stream.cc

实验要求我们实现下列函数:

C++ 复制代码
bool Writer::is_closed() const
void Writer::push( string data )
void Writer::close()
uint64_t Writer::available_capacity() const
uint64_t Writer::bytes_pushed() const
bool Reader::is_finished() const
uint64_t Reader::bytes_popped() const
string_view Reader::peek() const
void Reader::pop( uint64_t len )
uint64_t Reader::bytes_buffered() const
  • 首先在初始化时初始化流缓存的大小
C++ 复制代码
ByteStream::ByteStream( uint64_t capacity ) : capacity_( capacity )
{
  buffer_.reserve( capacity );
}

bool Writer::is_closed() const

返回isclosed_即可
*

void Writer::push( string data )

首先判断流是否关闭is_closed(),如关闭则return

后赋len值为字节流大小data.size()与可用容量available_capacity()的最小值(防止越界)

buffer_加入特定长度的data

bytes_pushed_累加len
*

void Writer::close()

isclosed_赋值为true
*

uint64_t Writer::available_capacity() const

返回capacity_-buffer_.size()
*

uint64_t Writer::bytes_pushed() const

返回bytes_pushed_
*

bool Reader::is_finished() const

Writer写入关闭且全部读取完后才会关闭Reader

return isclosed_ && buffer_.size() == 0
*

uint64_t Reader::bytes_popped() const

返回bytes_poped_
*

string_view Reader::peek() const

构建string_view sv范围为buffer_的有效长度的字符串

string_view sv( buffer_.data(), min( static_cast<uint64_t>(1024), bytes_buffered() ) );

static_cast<uint64_t>(1024)指的是不超过这个指标
*

void Reader::pop( uint64_t len )

buffer_进行弹出操作buffer_.erase(buffer_.begin(), buffer_.begin() + len )

再对bytes_poped_累加len
*

uint64_t Reader::bytes_buffered() const

返回buffer_.size()

则总代码src/byte_stream.cc为:

C++ 复制代码
#include "byte_stream.hh"

using namespace std;

ByteStream::ByteStream( uint64_t capacity ) : capacity_( capacity )
{
  buffer_.reserve( capacity );
}

bool Writer::is_closed() const
{
  // Your code here.
  return isclosed_;
}

void Writer::push( string data )
{
  if ( is_closed() )
    return;
  // Your code here.
  uint64_t len = min( data.size(), available_capacity() );
  buffer_ += data.substr( 0, len );
  bytes_pushed_ += len;
}

void Writer::close()
{
  // Your code here.
  isclosed_ = true;
}

uint64_t Writer::available_capacity() const
{
  // Your code here.
  return capacity_ - buffer_.size();
}

uint64_t Writer::bytes_pushed() const
{
  // Your code here.
  return bytes_pushed_;
}

bool Reader::is_finished() const
{
  // Your code here.
  return isclosed_ && buffer_.size() == 0;
}

uint64_t Reader::bytes_popped() const
{
  // Your code here.
  return bytes_poped_;
}

string_view Reader::peek() const
{
  // Your code here.
  string_view sv( buffer_.data(), min( static_cast<uint64_t>( 1024 ), bytes_buffered() ) );
  return sv;
}

void Reader::pop( uint64_t len )
{ // Your code here.
  buffer_.erase( buffer_.begin(), buffer_.begin() + len );
  bytes_poped_ += len;
}

uint64_t Reader::bytes_buffered() const
{
  // Your code here.
  return buffer_.size();
}

测试指令: cmake --build build --target check0

相关推荐
_oP_i1 小时前
HTTP 请求Media typetext/plain application/json text/json区别
网络协议·http·json
OkeyProxy2 小时前
HTTP、HTTPS和SOCKS5代理協議
网络协议·https·云计算·代理服务器·海外ip代理
zquwei3 小时前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
群联云防护小杜4 小时前
如何给负载均衡平台做好安全防御
运维·服务器·网络·网络协议·安全·负载均衡
ihengshuai4 小时前
HTTP协议及安全防范
网络协议·安全·http
a_weng087 小时前
CS 144 check6: buiding an IP router
网络·网络协议·计算机网络
码农丁丁8 小时前
[前端]HTTP库Axios
前端·网络协议·http·aixos
carterslam8 小时前
解决:websocket 1002 connection rejected 426upgrade required
网络·websocket·网络协议
G丶AEOM8 小时前
UDP基本了解
网络·网络协议
m0_748232929 小时前
Android Https和WebView
android·网络协议·https