当前位置: 首页 > news >正文

C++仿mudo库高并发服务器项目:Buffer模块

前言

本篇文章所讲的是本人的个人项目仿muduo库高并发服务器中的Buffer模块实现部分。

Buffer模块介绍:

Buffer类⽤于实现⽤⼾态缓冲区,提供数据缓冲,取出等功能。

  • 功能:用于实现通信套接字的用户态缓冲区

  • 意义:

    1. 防止接收到的数据不是一条完整的数据(提示:TCP面向字节流),因此对接收的数据进行缓冲
    2. 对客户端响应的数据,应该是在套接字可写的情况下进行发送
  • 功能设计:

    1. 向缓冲区中添加数据
    2. 从缓冲区中取出数据

实现思路:

  1. 实现缓冲区得有一块内存空间,采用vector,vector底层其实使用的就是一个线性的内存空间。

    这里不使用string作为容器是因为,缓冲器要存储的数据很大可能会包含字符0等字符,而string的方法往往会将它识别为数据结尾

  2. 要素:

    1. 默认的空间大小。

    2. 当前的读取数据位置。

    3. 当前的写入数据位置。

记录当前读取位置和当前写入位置是因为,在数据被读走时我们不需要移动数据,只需要更新下一次读取位置即可,插入时同理。

image-20251022230348146

写入操作:

当前写入位置在哪,就在哪写,当待写入空间大小,无法满足接下来的写入需求,这时我们就面临两种选择:

  1. 待写入数据所需空间大小<待写入空间+可覆盖空间,这种情况下我们只需要移动数据到容器开始处,再写入待写入数据即可。
  2. 待写入数据所需空间大小>待写入空间+可覆盖空间,这种情况下我们只能选择对缓存空间扩容。

读取操作:

当前读取位指向哪里,就从哪里开始读取,不过前提是得有数据可读;而可读数据的大小,是用当前写入位置减去当前读取位置来计算的。

代码实现:

const uint64_t BUFFER_DEFAULT_SIZE = 1024; 
class Buffer
{
private:std::vector<char> _buffer;//使用vector进行内存空间管理uint64_t _reader_idx;//读偏移uint64_t _write_idx;//写偏移public:Buffer():_reader_idx(0),_write_idx(0),_buffer(BUFFER_DEFAULT_SIZE){}char* Begin(){ return &*_buffer.begin(); }//获取当前写入起始地址char* WritePosition(){return Begin() + _write_idx;}//获取当前读取起始地址char* ReadPosition(){return Begin() + _reader_idx;}//获取缓冲区末尾空闲空间大小uint64_t TailIdleSize(){return _buffer.size() - _write_idx;}//获取缓冲区起始空闲空间大小uint64_t HeadIdleSize(){return _reader_idx;}//获取可读数据大小uint64_t ReadAbleSize(){return _write_idx - _reader_idx;}//将读偏移向后移动void MoveReadOffset(uint64_t len){if(len == 0) return;//必须小于可读空间大小assert(ReadAbleSize() >= len);_reader_idx += len;}//将写偏移向后移动void MoveWriteOffset(uint64_t len){//必须小于尾部空间大小assert(TailIdleSize() >= len);_write_idx += len;}//确保可写空间足够lenvoid EnsureWriteSpace(uint64_t len){//尾部空间够,直接返回if(TailIdleSize() >= len) return;//总体空间够,将数据平移到最开始,为后面腾位置if(TailIdleSize() + HeadIdleSize() >= len){//保存一下可读数据大小uint64_t rsz = ReadAbleSize();std::copy(ReadPosition(),ReadPosition() + rsz,Begin());//可读数据拷贝到起始位置_reader_idx = 0;_write_idx = rsz;}//不够,扩容else{_buffer.resize(_write_idx + len);}}//写入数据void Write(const void* date,uint64_t len){//保证空间足够if(len == 0) return;EnsureWriteSpace(len);//将数据拷贝进去const char* d = (const char*)date;std::copy(d,d + len,WritePosition());}//写入数据并且更新写指针void WriteAndPush(const void* date,uint64_t len){Write(date,len);MoveWriteOffset(len);}//写入一个字符串void WriteString(const std::string& date){Write(date.c_str(),date.size());}//写入一个字符串并且更新写指针void WriteStringAndPush(const std::string& date){WriteString(date);MoveWriteOffset(date.size());}//写入一个Buffervoid WriteBuffer(Buffer& date){Write(date.ReadPosition(),date.ReadAbleSize());}//写入一个Buffer并且更新写指针void WriteBufferAndPush(Buffer& date){Write(date.ReadPosition(),date.ReadAbleSize());MoveWriteOffset(date.ReadAbleSize());}//读取数据void Read(void* buf,uint64_t len){//获取数据的长度必须小于可读数据assert(len <= ReadAbleSize());std::copy(ReadPosition(),ReadPosition() + len,(char*)buf);}//读取数据并且更新读指针void ReadAndPop(void* buf,uint64_t len){Read(buf,len);MoveReadOffset(len);}//读取一个长度为len的字符串std::string ReadString(uint64_t len){assert(len <= ReadAbleSize());std::string str;str.resize(len);Read(&str[0],len);return str;}//读取一个长度为len的字符串并且更新读指针std::string ReadStringAndPop(uint64_t len){assert(len <= ReadAbleSize());std::string str = ReadString(len);MoveReadOffset(len);return str;}//查找换行符char* FindCRLF(){char* res = (char*)memchr(ReadPosition(),'\n',ReadAbleSize());return res;}//获取一行字符串std::string GetLine(){//找到换行符位置char* pos = FindCRLF();if(pos == nullptr) return "";//+1是为了把换行符也取出来return ReadString(pos - ReadPosition() + 1);}//获取一行字符串并且更新读指针std::string GetLineAndPop(){std::string str = GetLine();MoveReadOffset(str.size());return str;}//清空缓冲区void Clear(){//偏移量归零_reader_idx = _write_idx = 0;}
};

测试代码:

#include "Buffer.hpp"int main()
{Buffer buf;for(int i=0;i<300;i++){std::string  ret = "hello linux "+std::to_string(i)+'\n';buf.WriteStringAndPush(ret);}while(buf.ReadAbleSize()>0){std::cout << buf.GetLineAndPop();}std::cout << buf.ReadAbleSize() << std::endl;std::string str1;str1 = buf.ReadStringAndPop(buf.ReadAbleSize());std::cout << str1 << std::endl;Buffer buf0;std::string str2="hello linux !!";buf0.WriteStringAndPush(str2);std::cout << buf0.ReadAbleSize() << std::endl;Buffer buf1;buf1.WriteBufferAndPush(buf0);std::cout << buf1.ReadAbleSize() << std::endl;return 0;
}

测试结果:

image-20251022233120681

http://www.dtcms.com/a/515488.html

相关文章:

  • 找能做网站的搜狗推广下架
  • 性能分析--perfetto工具使用
  • 【matlab】如何提取论文plot图中的数据
  • 手机网站开发的目的ppt免费背景图片
  • Java 核心知识点查漏补缺(一)
  • UE5 C++ CVar控制台命令字段使用
  • 从图像处理到AI识别:直播美颜sdk如何实现高效一键美颜?
  • ESD防护设计宝典(十三):电快速瞬变脉冲群(EFT)防护与整改
  • 做百度推广去些网站加客户二级域名免费申请网站
  • 婚介 东莞网站建设西部数码网站源码
  • 云计算实验4——CentOS中HBase的安装
  • Excel文件中的VBA脚本,在文件使用WPS编辑保存后无法执行
  • LLD(详细设计文档)输出标准模板
  • 【山西政务服务网-注册_登录安全分析报告】
  • 云原生安全深度实战:从容器安全到零信任架构
  • Java导出写入固定Excel模板数据
  • 合肥网站建设模板系统html怎么做商品页面
  • uniapp微信小程序页面跳转后定时器未清除问题解析与解决方案
  • 《从“直接对话”到 “集成开发调用”:智谱 GLM-4.6 引领 Coding 场景的效率跃迁》
  • 数据中心基础设施等级
  • 关于架空输电线识别树障or测距相关论文阅读
  • [go 面试] 深入理解并发控制:掌握锁的精髓
  • TypeScript 面试题及详细答案 100题 (61-70)-- 泛型(Generics)
  • 全球外贸网站制作教程icp网站快速备案
  • 《Hiding Images in Diffusion Models by Editing Learned Score Functions》 论文阅读
  • 频率分集阵列雷达——论文阅读
  • 网站备案信息如何下载潍坊市住房和城乡建设局网站下载
  • 比较好的企业网站百度举报网站
  • 数据库加密技术
  • nginx配置内嵌网页