前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenBuffer用于解析网络数据流,解决TCP粘包问题

OpenBuffer用于解析网络数据流,解决TCP粘包问题

原创
作者头像
linyouhappy
修改2023-07-20 17:32:19
6620
修改2023-07-20 17:32:19
举报
文章被收录于专栏:OpenLinyouOpenLinyou

OpenBuffer

OpenBuffer 用于读写解析二进制流,解决TCP粘包问题,针对网络数据流而设计。

https://github.com/OpenMiniServer

跨平台支持

Windows、linux、Mac、iOS、Android等跨平台设计

编译和执行

请安装cmake工具,用cmake可以构建出VS或者XCode工程,就可以在vs或者xcode上编译运行。

源代码:https://github.com/OpenMiniServer/openbuffer

代码语言:txt
复制
git clone https://github.com/OpenMiniServer/openbuffer
cd ./openbuffer
mkdir build
cd build
cmake ..
#如果是win32,在该目录出现openbuffer.sln,点击它就可以启动vs写代码调试
make
./test

全部源文件

  • src/openbuffer.h
  • src/openbuffer.cpp

技术特点

OpenBuffer的技术特点:

  1. 对于添加数据push操作,使用节点链表来管理内存。每次push数据,数据存储到一个节点上,超过节点容量,就会创建新的节点进行存储。
  2. 从OpenBuffer读取数据,先把全部节点上的数据进行合并,存储到连续的内存上,然后释放对应节点的内存。
  3. 支持读写固定长度整数和不固定长度整数。

1.序列化与反序列化

支持整数,可变长整数序列化。采用小端编码。

代码语言:C++
复制
#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.解析网络数据包

模拟socket数据包,解析http报文。解决HTTP沾包问题。

代码语言:C++
复制
#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 OpenBufferOpenBuffer";
    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;
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OpenBuffer
    • 跨平台支持
      • 编译和执行
        • 全部源文件
          • 技术特点
            • 1.序列化与反序列化
              • 2.解析网络数据包
              相关产品与服务
              数据保险箱
              数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档