CS144 lab0

ops/2025/2/19 9:11:47/

webget

思路: 

创建TCP套接字:使用系统调用如 socket() 创建一个TCP套接字。
设定服务器地址:根据服务器的IP地址和端口号构造地址结构。
连接服务器:使用 connect() 方法和服务器地址来建立TCP连接。
发送HTTP请求:构建合适的HTTP请求字符串。
使用套接字的文件描述符,通过 write() 或类似方法发送请求到服务器。
接收响应:循环使用 read() 从套接字读取数据到缓冲区,处理TCP的分片和粘包问题。
解析HTTP响应数据,按需处理(如保存数据、打印等)。
关闭连接:读取完所有数据后,使用 close() 关闭套接字,释放资源。

需要注意的是:

(1)通常情况下,这里的 "service" 指的是端口号(如80用于HTTP,443用于HTTPS) 

(2)HTTP头的每一行都应以 "\r\n" 结尾,并在整个请求的末尾加上一个额外的 "\r\n" 来结束请求。

(3)TCP是一个面向流的协议,EOF的判断通常是read函数返回0,表示对端关闭了连接

(4)文件描述符类似IO流的概念,文件描述符提供了一种抽象接口,用于在程序和操作系统之间传递文件和其他输入/输出设备的操作。

(5)在理想情况下,HTTP响应的所有数据应该能够一次性存储到足够大的缓冲区中。

(6)如果响应数据量较大,无法确定其大小,或者存在限制(如内存限制),则可能需要分批次地读取数据,即通过循环读取的方式

(7)在循环读取数据的过程中,通过初始化变量(如read_offset = 0),读取一定数量的数据(如100字节),然后更新变量(如read_offset += 100),以确保后续读取操作能够从正确位置开始,以保证数据的连续性和完整性。

(8)当前文件描述符的行为已经隐含地处理了读取位置的跟踪(int fd_num())实现了read_offset的功能。

最新代码:

void get_URL(const std::string& host, const std::string& path) {TCPSocket client;Address server(host, "http");  // Port should be 80 by default for HTTPclient.connect(server);// Properly formatted HTTP GET requestclient.write("GET " + path + " HTTP/1.1\r\n");client.write("Host: " + host + "\r\n");client.write("Connection: close\r\n\r\n");  // Note the double \r\nstd::string response;std::string buffer;while (!client.eof()) {buffer.clear();  // Clear the buffer to avoid accumulating old dataclient.read(buffer);response += buffer;  // Append new data to the complete response}std::cout << response;client.close();
}

测试结果: 

ubun22@DESKTOP-1VEP92H:/mnt/e/Web/minnow$ cmake --build build --target check_webget
Test project /mnt/e/Web/minnow/buildStart 1: compile with bug-checkers
1/2 Test #1: compile with bug-checkers ........   Passed    4.88 secStart 2: t_webget
2/2 Test #2: t_webget .........................   Passed    1.66 sec100% tests passed, 0 tests failed out of 2Total Test time (real) =   6.69 sec
Built target check_webget
ubun22@DESKTOP-1VEP92H:/mnt/e/Web/minnow$ 

An in-memory reliable byte stream :

注意:

(1)字节流close后,不需要把buffer置为空

(2)只有pop可能会影响position的值

(3)peek()就是直接返回buffer中从position到结尾的视图

最新代码:

byte_stream.cc:

bool Writer::is_closed() const
{return close_;
}void Writer::push( string data )
{if ( is_closed() ) {return;}uint64_t available_space = available_capacity();uint64_t data_size = data.size();uint64_t push_size = std::min( available_space, data_size );bytes_pushed_ += push_size;buffer_ += data.substr( position_, push_size );return;
}void Writer::close()
{close_ = true;return;
}uint64_t Writer::available_capacity() const
{return capacity_ - buffer_.size();
}uint64_t Writer::bytes_pushed() const
{return bytes_pushed_;
}bool Reader::is_finished() const
{if ( close_ && !buffer_.size() ) {return true;} else {return false;}
}uint64_t Reader::bytes_popped() const
{return bytes_popped_;
}std::string_view Reader::peek() const
{if ( position_ < buffer_.size() ) {// 如果缓冲区中有未读取的字节,则返回下一个字节的视图return std::string_view( &buffer_[position_], buffer_.size() - position_ );} else {// 如果缓冲区已经读取完毕,则返回一个空的 string_viewreturn std::string_view();}
}void Reader::pop( uint64_t len )
{if ( is_finished() ) {return;}uint64_t buffer_size = bytes_buffered();buffer_ = buffer_.substr( len, buffer_size );bytes_popped_ += len;if ( position_ >= len ) {position_ -= len;}return;
}uint64_t Reader::bytes_buffered() const
{return buffer_.size();
}

byte_stream.hh:

#pragma once#include <cstdint>
#include <string>
#include <string_view>class Reader;
class Writer;class ByteStream
{
public:explicit ByteStream( uint64_t capacity );// Helper functions (provided) to access the ByteStream's Reader and Writer interfacesReader& reader();const Reader& reader() const;Writer& writer();const Writer& writer() const;void set_error() { error_ = true; };       // Signal that the stream suffered an error.bool has_error() const { return error_; }; // Has the stream had an error?protected:// Please add any additional state to the ByteStream here, and not to the Writer and Reader interfaces.uint64_t capacity_;std::string buffer_ = "";uint64_t position_ = 0;uint64_t bytes_popped_ = 0; // Initialize to zerouint64_t bytes_pushed_ = 0; // Initialize to zerobool close_ = false;        // Initialize to falsebool error_ = false;        // Initialize to false
};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.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_view peek() const; // Peek at the next bytes in the buffervoid pop( uint64_t len );      // Remove `len` bytes from the bufferbool is_finished() const;        // Is the stream finished (closed and fully popped)?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 );

测试结果: 

ubun22@DESKTOP-1VEP92H:/mnt/e/Web/minnow$ cmake --build build --target check0
Test project /mnt/e/Web/minnow/buildStart  1: compile with bug-checkers1/10 Test  #1: compile with bug-checkers ........   Passed    2.38 secStart  2: t_webget2/10 Test  #2: t_webget .........................   Passed    1.65 secStart  3: byte_stream_basics3/10 Test  #3: byte_stream_basics ...............   Passed    0.20 secStart  4: byte_stream_capacity4/10 Test  #4: byte_stream_capacity .............   Passed    0.26 secStart  5: byte_stream_one_write5/10 Test  #5: byte_stream_one_write ............   Passed    0.18 secStart  6: byte_stream_two_writes6/10 Test  #6: byte_stream_two_writes ...........   Passed    0.21 secStart  7: byte_stream_many_writes7/10 Test  #7: byte_stream_many_writes ..........   Passed    0.23 secStart  8: byte_stream_stress_test8/10 Test  #8: byte_stream_stress_test ..........   Passed    0.20 secStart 37: compile with optimization9/10 Test #37: compile with optimization ........   Passed    1.95 secStart 38: byte_stream_speed_testByteStream throughput: 1.02 Gbit/s
10/10 Test #38: byte_stream_speed_test ...........   Passed    0.18 sec100% tests passed, 0 tests failed out of 10Total Test time (real) =   7.72 sec
Built target check0


http://www.ppmy.cn/ops/8956.html

相关文章

ProbeManager:一款功能强大的入侵检测系统集中化管理工具

关于ProbeManager ProbeManager是一款功能强大的入侵检测系统集中化管理工具&#xff0c;该工具旨在简化检测探针的部署任务&#xff0c;并将其所有功能集中在一个地方。 一般来说&#xff0c;很多入侵检测系统&#xff08;IDS&#xff09;包括其软件及规则都不会定期更新&…

【HC32L110】华大低功耗单片机启动文件详解

本文主要记录华大低功耗单片机 HC32L110 的 汇编启动过程&#xff0c;包括startup_hc32l110启动文件详细注释 版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.…

【AI+大模型】Meta发布最强开源大模型Llama 3

就在昨天4.18&#xff0c; 美国科技巨头Meta推出了其最强大的开源人工智能(AI)模型Llama 3。Meta提到&#xff0c;他们为Llama 3模型输入的数据量是Llama 2的七倍&#xff0c;这可能有助于提高模型的性能和准确性。还利用了由AI生成的“合成”数据来加强模型在编码和推理等特定…

git如何删除错误提交到remote的某个分支?(git push origin --delete featre/xxx_featre)

缘起 其实本质就是删除远端的一个分支&#xff0c;但是本地不删除。 什么场景可能出现&#xff0c;假设你同事有一个remote的仓库叫做origin&#xff0c;你自己有一个remote仓库叫做mypriv&#xff0c;你是从他的仓库copy的仓库的。但是本地代码同时对应两个remote。 为什么要…

HarmonyOS ArkUI实战开发-窗口模块(Window)

窗口模块用于在同一物理屏幕上&#xff0c;提供多个应用界面显示、交互的机制。 对应用开发者而言&#xff0c;窗口模块提供了界面显示和交互能力。对于终端用户而言&#xff0c;窗口模块提供了控制应用界面的方式。对于操作系统而言&#xff0c;窗口模块提供了不同应用界面的…

Kubernetes Kafka 系列|MirrorMaker 2 同步数据

一、MirrorMaker 2介绍 MirrorMaker 2&#xff08;简称MM2&#xff09;是Apache Kafka的一个工具&#xff0c;主要用于跨Kafka集群的数据复制和同步。相比早期的MirrorMaker 1&#xff08;简称MM1&#xff09;&#xff0c;MirrorMaker 2在设计和功能上有了显著的提升&#xff…

【python】如何通过python来发送短信

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

element plus el-date-picker type=“datetime“ 限制年月日 时分秒选择

如何限制el-date-picker组件的时分秒选中&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 文档 文档在这里&#xff1a;DateTimePicker 日期时间选择器 | Element Plus 它提供的disabled-date给我们来限制日期选择 nice&#xff01;&…