項(xiàng)目完整版在:
一、buffer模塊: 緩沖區(qū)模塊
Buffer模塊是一個(gè)緩沖區(qū)模塊,用于實(shí)現(xiàn)通信中用戶態(tài)的接收緩沖區(qū)和發(fā)送緩沖區(qū)功能。
二、提供的功能
存儲(chǔ)數(shù)據(jù),取出數(shù)據(jù)
三、實(shí)現(xiàn)思想
1.實(shí)現(xiàn)換出去得有一塊內(nèi)存空間,采用vector ,vector底層是一個(gè)線性的內(nèi)存空間!
(一)要素
1.默認(rèn)空間大小
2.當(dāng)前的讀取數(shù)據(jù)位置!
3.當(dāng)前的寫(xiě)入數(shù)據(jù)位置!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-729418.html
(二)操作
- 寫(xiě)入位置
當(dāng)前寫(xiě)入位置指向哪里,從哪里開(kāi)始寫(xiě)入
如果后續(xù)剩余空間不夠了! - 考慮整體緩沖區(qū)空閑空間是否足夠?。ㄒ?yàn)樽x位置也會(huì)向后偏移,前后有可能有空閑空間)
足夠:將數(shù)據(jù)移動(dòng)到起始位置
不夠:擴(kuò)容,從當(dāng)前寫(xiě)位置開(kāi)始擴(kuò)容足夠大小!
數(shù)據(jù)一旦寫(xiě)入成功,當(dāng)前寫(xiě)位置,向后偏移! - 讀取數(shù)據(jù)
當(dāng)前的讀取位置指向哪里,就從哪里開(kāi)始讀取,前提是有數(shù)據(jù)可讀
可讀數(shù)據(jù)大小:當(dāng)前寫(xiě)入位置,減去當(dāng)前讀取位置!
(三)框架設(shè)計(jì)
class buffer {
private:
std::vector<char> _buffer;
// 位置是一個(gè)相對(duì)偏移量,而不是絕對(duì)地址!
uint64_t _read_idx; // 讀位置
uint64_t _write_idx; // 寫(xiě)位置
public:
1. 獲取當(dāng)前寫(xiě)的位置
2. 確??蓪?xiě)空間足夠
3. 獲取前沿空間大小
4. 獲取后沿空間大小
5. 將寫(xiě)入據(jù)位置向后移動(dòng)指定長(zhǎng)度
6. 獲取當(dāng)前讀取位置的地址!
7. 獲取可讀空間大小
8. 將讀位置向后移動(dòng)指定長(zhǎng)度!
9. clear
四、實(shí)現(xiàn)代碼
#include <ctime>
#include <cstring>
#include <iostream>
#include <vector>
#include <cassert>
#include <string>
using namespace std;
#define BUFFER_SIZE 1024
class Buffer {
private:
std::vector<char> _buffer; // 使用vector進(jìn)行內(nèi)存空間管理
uint64_t _read_idx; // 讀偏移
uint64_t _write_idx; // 寫(xiě)偏移
public:
Buffer():_read_idx(0),_write_idx(0),_buffer(BUFFER_SIZE) {}
char* begin() {return &*_buffer.begin();}
// 獲取當(dāng)前寫(xiě)入起始地址
char *writePosition() { return begin() + _write_idx;}
// 獲取當(dāng)前讀取起始地址
char *readPosition() { return begin() + _read_idx; }
// 獲取緩沖區(qū)末尾空間大小 —— 寫(xiě)偏移之后的空閑空間,總體大小減去寫(xiě)偏移
uint64_t tailIdleSize() {return _buffer.size() - _write_idx; }
// 獲取緩沖區(qū)起始空間大小 —— 讀偏移之前的空閑空間
uint64_t handIdleSize() {return _read_idx ;}
// 獲取可讀空間大小 = 寫(xiě)偏移 - 讀偏移
uint64_t readAbleSize() {return _write_idx - _read_idx ;}
// 將讀偏移向后移動(dòng)
void moveReadOffset(uint64_t len) {
// 向后移動(dòng)大小必須小于可讀數(shù)據(jù)大小
assert(len <= readAbleSize());
_read_idx += len;
}
// 將寫(xiě)偏移向后移動(dòng)
void moveWriteOffset(uint64_t len) {
assert(len <= tailIdleSize());
_write_idx += len;
}
void ensureWriteSpace(uint64_t len) {
// 確??蓪?xiě)空間足夠 (整體空間夠了就移動(dòng)數(shù)據(jù),否則就擴(kuò)容?。?
if (tailIdleSize() >= len) return;
// 不夠的話 ,判斷加上起始位置夠不夠,夠了將數(shù)據(jù)移動(dòng)到起始位置
if (len <= tailIdleSize() + handIdleSize()) {
uint64_t rsz = readAbleSize(); //幫當(dāng)前數(shù)據(jù)大小先保存起來(lái)
std::copy(readPosition(),readPosition() + rsz,begin()); // 把可讀數(shù)據(jù)拷貝到起始位置
_read_idx = 0; // 讀歸為0
_write_idx = rsz; // 可讀數(shù)據(jù)大小是寫(xiě)的偏移量!
}
else { // 總體空間不夠!需要擴(kuò)容,不移動(dòng)數(shù)據(jù),直接給寫(xiě)偏移之后擴(kuò)容足夠空間即可!
_buffer.resize(_write_idx + len);
}
}
// 寫(xiě)入數(shù)據(jù)
void Write(const void *data,uint64_t len) {
ensureWriteSpace(len);
const char *d = (const char*) data;
std::copy(d,d + len,writePosition());
}
void WriteAndPush(void* data,uint64_t len) {
Write(data,len);
moveWriteOffset(len);
}
void WriteStringAndPush(const std::string &data) {
writeString(data);
moveWriteOffset(data.size());
}
void writeString(const std::string &data) {
return Write(data.c_str(),data.size());
}
void writeBuffer(Buffer &data) {
return Write(data.readPosition(),data.readAbleSize());
}
void writeBufferAndPush(Buffer &data) {
writeBuffer(data);
moveWriteOffset(data.readAbleSize());
}
std::string readAsString (uint64_t len) {
assert(len <= readAbleSize());
std::string str;
str.resize(len);
Read(&str[0],len);
return str;
}
void Read(void *buf,uint64_t len) {
// 讀取數(shù)據(jù) 1. 保證足夠的空間 2.拷貝數(shù)據(jù)進(jìn)去
// 要求獲取的大小必須小于可讀數(shù)據(jù)大??!
assert(len <= readAbleSize());
std::copy(readPosition(),readPosition() + len,(char*)buf);
}
void readAndPop(void *buf,uint64_t len) {
Read(buf,len);
moveReadOffset(len);
}
// 逐步調(diào)試?。。。?!
std::string ReadAsStringAndPop(uint64_t len) {
assert(len <= readAbleSize());
std::string str = readAsString(len);
moveReadOffset(len);
return str;
}
char* FindCRLF() {
char *res = (char*)memchr(readPosition(),'\n',readAbleSize());
return res;
}
// 通常獲取一行數(shù)據(jù),這種情況針對(duì)是:
std::string getLine() {
char* pos = FindCRLF();
if (pos == NULL) {
return "";
}
// +1 為了把換行數(shù)據(jù)取出來(lái)!
return readAsString(pos - readPosition() + 1);
}
std::string getLineAndPop() {
std::string str = getLine();
moveReadOffset(str.size());
return str;
}
void Clear() { // 清空緩沖區(qū)!clear
// 只需要將偏移量歸0即可!
_read_idx = 0;
_write_idx = 0;
}
};
五、進(jìn)行測(cè)試
#include "server.hpp"
using namespace std;
// 控制打印信息?。?!
#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL INF
#define LOG(level,format,...) do{\
if (level < LOG_LEVEL) break;\
time_t t = time(NULL);\
struct tm *ltm = localtime(&t);\
char tmp[23] = {0};\
strftime(tmp,31,"%H:%M:%S",ltm);\
fprintf(stdout,"[%s,%s:%d] " format "\n",tmp,__FILE__,__LINE__,##__VA_ARGS__);\
}while(0)
#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)
int main() {
Buffer buf;
std::string str = "hello!";
// buf.WriteStringAndPush(str);
// Buffer buf1;
// buf1.writeBufferAndPush(buf);
// std::string tmp;
// tmp = buf1.ReadAsStringAndPop(buf.readAbleSize());
// cout << tmp << endl;
// cout << buf.readAbleSize() << endl;
// cout << buf1.readAbleSize() << endl;
for (int i = 0; i < 300; i ++) {
std::string str = "hello" + std::to_string(i) + '\n';
buf.WriteStringAndPush(str);
}
while(buf.readAbleSize() > 0) {
string line = buf.getLineAndPop();
LOG("hello");
}
// string tmp;
// tmp = buf.ReadAsStringAndPop(buf.readAbleSize());
// cout << tmp << endl;
return 0;
}
中秋快樂(lè)!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-729418.html
到了這里,關(guān)于1.4.C++項(xiàng)目:仿muduo庫(kù)實(shí)現(xiàn)并發(fā)服務(wù)器之buffer模塊的設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!