OpenBuffer
OpenBuffer 用于讀寫解析二進制流臂痕,解決TCP粘包問題,針對網(wǎng)絡(luò)數(shù)據(jù)流而設(shè)計猿涨。
OpenLinyou開源項目致力于跨平臺服務(wù)器框架握童,在VS或者XCode上寫代碼,無需任何改動就可以編譯運行在Linux上叛赚,甚至是安卓和iOS.
OpenLinyou:https://github.com/openlinyou
https://gitee.com/linyouhappy
跨平臺支持
Windows澡绩、linux、Mac俺附、iOS肥卡、Android等跨平臺設(shè)計
編譯和執(zhí)行
請安裝cmake工具,用cmake可以構(gòu)建出VS或者XCode工程事镣,就可以在vs或者xcode上編譯運行步鉴。
源代碼:https://github.com/openlinyou/openbuffer
https://gitee.com/linyouhappy/openbuffer
git clone https://github.com/openlinyou/openbuffer
cd ./openbuffer
mkdir build
cd build
cmake ..
#如果是win32,在該目錄出現(xiàn)openbuffer.sln璃哟,點擊它就可以啟動vs寫代碼調(diào)試
make
./test
全部源文件
- src/openbuffer.h
- src/openbuffer.cpp
技術(shù)特點
OpenBuffer的技術(shù)特點:
- 對于添加數(shù)據(jù)push操作氛琢,使用節(jié)點鏈表來管理內(nèi)存。每次push數(shù)據(jù)随闪,數(shù)據(jù)存儲到一個節(jié)點上阳似,超過節(jié)點容量,就會創(chuàng)建新的節(jié)點進行存儲蕴掏。
- 從OpenBuffer讀取數(shù)據(jù)障般,先把全部節(jié)點上的數(shù)據(jù)進行合并调鲸,存儲到連續(xù)的內(nèi)存上,然后釋放對應(yīng)節(jié)點的內(nèi)存挽荡。
- 支持讀寫固定長度整數(shù)和不固定長度整數(shù)藐石。
1.序列化與反序列化
支持整數(shù),可變長整數(shù)序列化定拟。采用小端編碼于微。
#include <assert.h>
#include <string.h>
#include <string>
#include <vector>
#include "openbuffer.h"
using namespace open;
int main()
{
OpenBuffer openBuffer(256);
char data[256] = "Hello OpenBuffer!";
const std::string str = "Hello OpenLinyou!";
size_t len = strlen(data);
openBuffer.push(&len, sizeof(len));
openBuffer.push(data, len);
len = str.size();
openBuffer.pushUInt32(len);
openBuffer.push(str.data(), len);
openBuffer.pushUInt16(1616);
openBuffer.pushUInt32(3232);
openBuffer.pushUInt64(6464);
openBuffer.pushVInt32(0x79);
openBuffer.pushVInt32(0x80);
openBuffer.pushVInt32(0x4000);
openBuffer.pushVInt32(0x10000000);
openBuffer.pushVInt64(0x10000001);
std::vector<char> vectData;
len = 0;
openBuffer.pop(&len, sizeof(len));
vectData.resize(len);
openBuffer.pop(vectData.data(), len);
assert(memcmp(vectData.data(), data, len) == 0);
char ret[256] = {};
uint32_t len1 = 0;
openBuffer.popUInt32(len1);
openBuffer.pop(ret, len1);
assert(str == ret);
unsigned short u16 = 0;
openBuffer.popUInt16(u16);
assert(u16 == 1616);
uint32_t u32 = 0;
openBuffer.popUInt32(u32);
assert(u32 == 3232);
uint64_t u64 = 0;
openBuffer.popUInt64(u64);
assert(u64 == 6464);
uint64_t v32 = 0;
openBuffer.popVInt64(v32);
assert(v32 == 0x79);
uint64_t v32_1 = 0;
openBuffer.popVInt64(v32_1);
assert(v32_1 == 0x80);
uint64_t v32_2 = 0;
openBuffer.popVInt64(v32_2);
assert(v32_2 == 0x4000);
uint64_t v32_3 = 0;
openBuffer.popVInt64(v32_3);
assert(v32_3 == 0x10000000);
uint64_t v64 = 0;
openBuffer.popVInt64(v64);
assert(v64 == 0x10000001);
return 0;
}
2.解析網(wǎng)絡(luò)數(shù)據(jù)包
模擬socket數(shù)據(jù)包,解析http報文青自。解決HTTP沾包問題株依。
#include <assert.h>
#include <string.h>
#include <string>
#include <vector>
#include "openbuffer.h"
using namespace open;
int main()
{
std::vector<std::string> datas = {
"HTTP/1.1 200 OK@&Connection: keep-alive@&Content-Type: application/x-javascript@&",
"Date: Sat, 18 Mar 2023 08:11:44 GMT@&Strict-Transport-Security: max-age=31536000@&Traceco",
"de: 24764974122629742602031816@&Vary: Accept-Encoding@&"
};
std::string body = "Hello OpenBuffer!!Hello OpenBuffer!!";
datas.push_back("content-length:" + std::to_string(body.size()) + "@&");
datas.push_back("@&" + body);
datas.push_back("@&");
OpenBuffer openBuffer;
for (size_t x = 0; x < 10000; x++)
{
openBuffer.clear();
bool isHeader = true;
size_t k = 0;
std::string head;
for (size_t i = 0; i < datas.size(); ++i)
{
openBuffer.push(datas[i].data(), datas[i].size());
if (isHeader)
{
unsigned char* tmp = openBuffer.data();
for (; k < openBuffer.size() - 3; k++)
{
//find @&@&
if (tmp[k] == '@' && tmp[k + 1] == '&' && tmp[k + 2] == '@' && tmp[k + 3] == '&')
break;
}
if (k >= openBuffer.size() - 3) continue;
k += 4;
openBuffer.pop(head, k);
isHeader = false;
}
}
std::string test = body + "@&";
std::string buffer;
buffer.append((const char*)openBuffer.data(), openBuffer.size());
assert(test == buffer);
}
return 0;
}