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

Libevent TCP开发指南

一、概念

Libevent 提供了高效的 TCP 网络编程接口,使开发者能够轻松构建高性能的 TCP 服务器和客户端。本指南将详细介绍如何使用 Libevent 进行 TCP 网络开发。

核心组件

  1. 事件基 (event_base) - 事件处理的核心结构

  2. 事件 (event) - 表示单个事件

  3. 缓冲区事件 (bufferevent) - 带缓冲的 I/O 事件

  4. 监听器 (evconnlistener) - TCP 连接监听器

  5. 缓冲区 (evbuffer) - 高效的数据缓冲区

常用 API

事件基

  • event_base_new() - 创建新的事件基

  • event_base_free() - 释放事件基

  • event_base_dispatch() - 开始事件循环

  • event_base_loopexit() - 退出事件循环

事件

  • event_new() - 创建新事件

  • event_free() - 释放事件

  • event_add() - 添加事件到事件基

  • event_del() - 从事件基中删除事件

缓冲区事件

  • bufferevent_socket_new() - 创建新的缓冲区事件

  • bufferevent_setcb() - 设置回调函数

  • bufferevent_enable() - 启用事件

  • bufferevent_write() - 写入数据

  • bufferevent_read() - 读取数据

event与bufferevent

普通事件(event)‌:基础事件类型,用于监听文件描述符的可读/可写状态、信号、定时器等单一事件触发。用户需手动管理I/O操作和缓冲区的数据读写‌。比如:监听socket的可读事件后,需自行调用read()读取数据并处理粘包/分包问题‌。
缓冲区事件(bufferevent):高级封装的事件类型,内置输入/输出缓冲区(evbuffer结构体),自动处理底层I/O的读写操作和数据缓冲。用户只需通过回调函数处理已就绪的数据‌。比如:收到数据时自动填充输入缓冲区,触发读回调;用户调用bufferevent_write()时,数据先写入输出缓冲区,由libevent自动发送‌。

特性 普通事件(event) 缓冲区事件(bufferevent)
数据缓冲 需用户手动管理 内置输入/输出缓冲区,自动管理
水位控制 不支持 支持设置高/低水位标记‌
适用场景 信号、定时器、低层I/O控制 流式网络通信(如TCP服务)
多线程支持 需额外同步机制 提供线程安全的缓冲区操作接口‌

二、TCP 服务器开发

1. 基本服务器框架

#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <arpa/inet.h>

// 定义回调函数
void read_cb(struct bufferevent *bev, void *ctx);
void event_cb(struct bufferevent *bev, short events, void *ctx);
void accept_conn_cb(struct evconnlistener *listener, 
                   evutil_socket_t fd,
                   struct sockaddr *address, 
                   int socklen,
                   void *ctx);

int main() {
    // 1. 创建事件基
    struct event_base *base = event_base_new();
    if (!base) {
        fprintf(stderr, "Could not initialize libevent!\n");
        return 1;
    }

    // 2. 配置服务器地址
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8080);  // 监听8080端口
    sin.sin_addr.s_addr = htonl(INADDR_ANY);  // 监听所有接口

    // 3. 创建监听器
    struct evconnlistener *listener = evconnlistener_new_bind(
        base, accept_conn_cb, NULL,
        LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1,
        (struct sockaddr*)&sin, sizeof(sin));
    
    if (!listener) {
        fprintf(stderr, "Could not create a listener!\n");
        return 1;
    }

    // 4. 启动事件循环
    event_base_dispatch(base);

    // 5. 清理资源
    evconnlistener_free(listener);
    event_base_free(base);

    return 0;
}

2. 连接接受回调

void accept_conn_cb(struct evconnlistener *listener, 
                   evutil_socket_t fd,
                   struct sockaddr *address, 
                   int socklen,
                   void *ctx) {
    struct event_base *base = evconnlistener_get_base(listener);
    
    // 为新的客户端连接创建bufferevent
    struct bufferevent *bev = bufferevent_socket_new(
        base, fd, BEV_OPT_CLOSE_ON_FREE);
    
    if (!bev) {
        fprintf(stderr, "Error constructing bufferevent!");
        event_base_loopbreak(base);
        return;
    }

    // 设置回调函数
    bufferevent_setcb(bev, read_cb, NULL, event_cb, NULL);
    
    // 启用读写事件
    bufferevent_enable(bev, EV_READ | EV_WRITE);
    
    // 可选: 设置水位标记
    bufferevent_setwatermark(bev, EV_READ, 0, 4096); // 最大读取4096字节
}

3. 数据读取回调

void read_cb(struct bufferevent *bev, void *ctx) {
    struct evbuffer *input = bufferevent_get_input(bev);
    size_t len = evbuffer_get_length(input);
    
    // 分配缓冲区
    unsigned char *buffer = malloc(len + 1);
    
    // 从输入缓冲区读取数据
    bufferevent_read(bev, buffer, len);
    buffer[len] = '\0';
    
    printf("Received %zu bytes: %s\n", len, buffer);
    
    // 回显数据
    bufferevent_write(bev, buffer, len);
    
    free(buffer);
}

4. 事件处理回调

void event_cb(struct bufferevent *bev, short events, void *ctx)

相关文章:

  • Python Web 框架 django-vue3-admin快速入门 django后台管理
  • STM32智能手表——任务线程部分
  • anaconda安装 创建虚拟环境+pycharm中conda环境配置
  • 复杂的数据类型03--指针和数组
  • 线程等待与唤醒的几种方法与注意事项
  • Scala 正则表达式
  • 【技术白皮书】ChatBI架构设计:如何构建上下文感知的企业级问答引擎?
  • 搭建FTP服务器
  • Mac 终端命令大全
  • 太阳能储能路灯杆:点亮绿色未来的新篇章
  • 视频孪生赋能电力数字化转型:构建智能电网的未来蓝图
  • 图解AUTOSAR_SWS_CANNetworkManagement
  • APScheduler定时
  • root账号修改密码
  • 【WRF工具】GIS4WRF详细介绍:配置 WPS/WRF
  • Metabase:一个免费开源的BI平台
  • Vue Transition组件类名+TailwindCSS
  • 程序化广告行业(50/89):Cookie映射技术深度剖析
  • 中级:MyBatis面试题深度剖析
  • Qt - findChild
  • 殷墟出土鸮尊时隔50年首次聚首,北京新展“看·见殷商”
  • 刘小涛任江苏省委副书记
  • 最高人民法院原副院长唐德华逝世,享年89岁
  • 上海锦江乐园摩天轮正在拆除中,预计5月底6月初拆完
  • 坚持吃素,是不是就不会得高血脂了?
  • 鄂州交警通报致1死2伤车祸:女子操作不当引发,已被刑拘