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

使用 libevent 处理 TCP 粘包问题(基于 Content-Length 或双 \r\n)

在基于 libevent 的 TCP 服务器开发中,处理消息边界是常见需求。以下是两种主流分包方案的完整实现:

一、基于 Content-Length 的分包方案

1.1 数据结构设计

typedef struct {
    struct bufferevent *bev;
    int content_length;  // 当前消息的预期长度
    int received_bytes;  // 已接收字节数
    char *buffer;        // 消息缓冲区
    size_t buffer_size;  // 缓冲区大小
} tcp_session_t;

1.2 核心处理逻辑

void read_cb(struct bufferevent *bev, void *arg) {
    tcp_session_t *session = (tcp_session_t *)arg;
    struct evbuffer *input = bufferevent_get_input(bev);
    
    // 阶段1:读取消息头
    if (session->content_length == -1) {
        char *line = evbuffer_readln(input, NULL, EVBUFFER_EOL_CRLF);
        if (!line) return;  // 不完整的行
        
        // 解析Content-Length
        if (strstr(line, "Content-Length:") != NULL) {
            sscanf(line, "Content-Length: %d", &session->content_length);
            session->buffer = malloc(session->content_length + 1);
        }
        free(line);
        
        // 检查是否到达头部结束(空行)
        line = evbuffer_readln(input, NULL, EVBUFFER_EOL_CRLF);
        if (line && strlen(line) == 0) {
            free(line);
            if (session->content_length == -1) {
                // 没有Content-Length的简单消息
                session->content_length = evbuffer_get_length(input);
            }
        } else {
            return;  // 继续等待头部结束
        }
    }
    
    // 阶段2:读取消息体
    size_t avail = evbuffer_get_length(input);
    size_t need = session->content_length - session->received_bytes;
    size_t to_read = avail < need ? avail : need;
    
    evbuffer_remove(input, session->buffer + session->received_bytes, to_read);
    session->received_bytes += to_read;
    
    // 阶段3:完整消息处理
    if (session->received_bytes == session->content_length) {
        session->buffer[session->content_length] = '\0';
        process_complete_message(session->buffer);
        
        // 重置状态
        free(session->buffer);
        session->buffer = NULL;
        session->content_length = -1;
        session->received_bytes = 0;
    }
}

二、基于双 CRLF 的分包方案

2.1 数据结构设计

typedef struct {
    struct bufferevent *bev;
    int header_complete;  // 头部是否解析完成
    char *header;         // 消息头缓冲区
    char *body;           // 消息体缓冲区
    size_t body_len;      // 消息体长度
} tcp_session_t;

2.2 核心处理逻辑

void read_cb(struct bufferevent *bev, void *arg) {
    tcp_session_t *session = (tcp_session_t *)arg;
    struct evbuffer *input = bufferevent_get_input(bev);
    
    // 阶段1:解析消息头
    if (!session->header_complete) {
        char *line = evbuffer_readln(input, NULL, EVBUFFER_EOL_CRLF);
        if (!line) return;
        
        if (session->header == NULL) {
            session->header = malloc(1024);
            session->header[0] = '\0';
        }
        
        // 空行表示头部结束
        if (strlen(line) == 0) {
            session->header_complete = 1;
            free(line);
            
            // 检查是否有消息体(如POST请求)
            const char *content_len = strstr(session->header, "Content-Length:");
            if (content_len) {
                sscanf(content_len, "Content-Length: %zu", &session->body_len);
                session->body 
http://www.dtcms.com/a/106781.html

相关文章:

  • 操作系统高频(七)虚拟地址与页表
  • ADASH VA5 Pro中的route功能
  • electron 的 appData 和 userData 有什么区别
  • SPI高级特性分析
  • JavaScript instanceof 运算符全解析
  • 「DeepSeek-V3 技术解析」:无辅助损失函数的负载均衡
  • 双模多态驱动:DeepSeek-V3-0324与DeepSeek-R1医疗领域应用比较分析与混合应用讨论
  • 移动通信网络中漫游机制深度解析:归属网络与拜访网络的协同逻辑
  • PHP的相关配置和优化
  • openstack 查看所有项目配额的命令
  • SU CTF 2025 web 复现
  • tcp的粘包拆包问题,如何解决?
  • 【深度学习量化交易21】行情数据获取方式比测(2)——基于miniQMT的量化交易回测系统开发实记
  • 常见电源模块设计
  • ColPali:基于视觉语言模型的高效文档检索
  • 探索鸿蒙操作系统:迎接万物互联新时代
  • 【IOS webview】源代码映射错误,页面卡住不动
  • STM32单片机入门学习——第7节: [3-3] GPIO输入
  • 树莓派超全系列教程文档--(22)使用外部存储设备的相关操作
  • Spring Boot 集成Redis中 RedisTemplate 及相关操作接口对比与方法说明
  • #Linux内存管理# 假设设备上安装了一块2G的物理内存,在系统启动时,ARM Linux内核是如何映射的?
  • RAG 和 RAGFlow 学习笔记
  • 【VUE3】Pinia
  • ARM 性能分析工具:Streamline
  • 高并发内存池(二):Central Cache的实现
  • Java 进化之路:从 Java 8 到 Java 21 的重要新特性
  • 【爬虫基础】第三部分 爬虫请求库 1/4
  • Android 防抖和节流
  • 【Kafka基础】Kafka工作原理解析
  • 英语口语 -- 常用 1368 词汇