扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

bufferevent | 嵌入式网络通信缓冲层

2025/07/10
1289
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

libevent作为一款强大的事件驱动库,提供了bufferevent机制,极大地简化了异步网络编程,高效处理了数据收发。

本文我们一起来学习一下bufferevent。

一、bufferevent简介

bufferevent是libevent提供的高级抽象层,用于处理带缓冲的I/O操作。

它将底层的事件处理(如socket读写)与数据缓冲管理相结合,提供了统一且简洁的接口。

通过bufferevent,开发者无需手动管理底层的I/O事件,只需关注数据的读写逻辑。

核心特性

    • 自动缓冲区管理:内置输入/输出缓冲区,自动处理数据的读写和存储
    • 事件驱动:基于libevent的事件机制,支持异步非阻塞操作
    • 超时控制:可设置读写超时,防止长时间阻塞
    • SSL/TLS支持:原生支持安全通信,无需额外配置
    • 可扩展性:支持自定义过滤器,实现数据转换和处理
    • 线程安全:提供线程安全接口,适用于多线程环境

二、bufferevent实战

下面是一个基于bufferevent的简易TCP客户端示例,展示了如何使用bufferevent进行数据收发。

#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

// 读取回调函数
void read_cb(struct bufferevent *bev, void *ctx) {
    char buffer[1024];
    int n;
    
    // 从输入缓冲区读取数据
    while ((n = bufferevent_read(bev, buffer, sizeof(buffer)-1)) > 0) {
        buffer[n] = '';
        printf("收到服务器消息: %s", buffer);
    }
}

// 事件回调函数
void event_cb(struct bufferevent *bev, short events, void *ctx) {
    if (events & BEV_EVENT_CONNECTED) {
        printf("已连接到服务器n");
        // 连接成功后发送数据
        bufferevent_write(bev, "Hello, server!n", strlen("Hello, server!n"));
    } elseif (events & BEV_EVENT_ERROR) {
        printf("发生错误: %sn", strerror(errno));
    } elseif (events & (BEV_EVENT_EOF | BEV_EVENT_TIMEOUT)) {
        printf("连接关闭或超时n");
    }
    
    // 发生错误时释放资源
    if (events & (BEV_EVENT_ERROR | BEV_EVENT_EOF | BEV_EVENT_TIMEOUT)) {
        bufferevent_free(bev);
    }
}

int main(int argc, char **argv) {
    struct event_base *base;
    struct bufferevent *bev;
    struct sockaddr_in server_addr;
    
    // 初始化事件基
    base = event_base_new();
    if (!base) {
        fprintf(stderr, "创建事件基失败n");
        return1;
    }
    
    // 配置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(9999);
    evutil_inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
    
    // 创建bufferevent
    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
    if (!bev) {
        fprintf(stderr, "创建bufferevent失败n");
        event_base_free(base);
        return1;
    }
    
    // 设置回调函数
    bufferevent_setcb(bev, read_cb, NULL, event_cb, NULL);
    bufferevent_enable(bev, EV_READ | EV_WRITE);
    
    // 连接服务器
    if (bufferevent_socket_connect(bev, 
                                 (struct sockaddr *)&server_addr,
                                 sizeof(server_addr)) < 0) {
        fprintf(stderr, "连接失败n");
        bufferevent_free(bev);
        event_base_free(base);
        return1;
    }
    
    // 进入事件循环
    event_base_dispatch(base);
    
    // 清理资源
    event_base_free(base);
    return0;
}

编译:

gcc -o bufferevent_test bufferevent_test.c -I/path/to/libev
ent/include -L/path/to/libevent/lib -levent -Wl,-rpath=/path/to/libevent/lib

需要先安装libevent,服务端参考:嵌入式开发必备:开源事件驱动库 libevent

运行:

三、bufferevent核心机制

1、核心机制

(1)缓冲区操作核心

输入缓冲区:使用 evbuffer 管理接收到的数据,支持水位控制和回调
输出缓冲区:使用 evbuffer 管理待发送的数据,支持高效的批量写入

(2)事件触发条件

读回调:当输入缓冲区数据量 >= 读低水位 或 发生错误 / EOF
写回调:当输出缓冲区数据量 <= 写低水位 或 发生错误

(3)挂起机制

读挂起:当输入缓冲区数据量 >= 读高水位 或 手动挂起
写挂起:当输出缓冲区数据量 >= 写高水位 或 底层写入阻塞

(4)线程安全

使用递归锁保护共享数据结构

提供 bufferevent_lock()/bufferevent_unlock() 接口

延迟回调机制避免在锁内执行用户代码

2、源码

bufferevent的源码主要分布在以下文件中:

libevent/
├── bufferevent.c         # 基础bufferevent实现
├── bufferevent_filter.c  # 过滤器实现
├── bufferevent_ssl.c     # SSL/TLS支持
├── evbuffer.c            # 缓冲区实现
├── evbuffer_list.c       # 链表式缓冲区实现

bufferevent 采用了 策略模式 设计,通过 struct bufferevent_ops 实现多态行为:

不同类型的 bufferevent(如 socket、filter、SSL)共享同一套接口,通过 be_ops 指针调用各自的实现函数。

(1)bufferevent的数据结构定义如下:

(2)水位控制结构:

读水位:当输入缓冲区数据超过 high 时停止读取,低于 low 时恢复

写水位:当输出缓冲区数据低于 low 时触发 writecb,超过 high 时暂停写入

(3)数据读取事件触发流程

bufferevent_socket_new -> bufferevent_readcb -> bufferevent_trigger_nolock_ -> bufferevent_run_readcb_ -> bufev->readcb

(4)数据写入触发流程

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

本公众号专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,公众号内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!