libevent是一套轻量级的网络库,基于事件驱动开发。能够实现多线程的多路复用和注册事件响应。本文将介绍libevent的基本功能以及如何利用libevent开发一个线程池。 一. 使用指南 监听服务和注册连接事件
libevent是一个基于事件驱动的网络库,通过在一个事件循环上注册不同的事件以完成线程多路复用。由于libevent采用c语言开发,为了使用方便我们可以将它的功能通过面向对象的设计模式用c++来封装。下面是对常用函数的详细介绍:
(1)event_base_new():创建(初始化)event_base
event_base代表了一个事件循环上下文,所有需要基于这个事件循环的事件都需要注册在它的上面。如果创建成功,最后需要使用event_base_free()来释放资源。
(2)evconnlistener_new_bind():绑定一个本地端口并注册网络监听事件
参数说明:
struct event_base* base 前文创建好的base,事件将关联到这个事件循环上
evconnlistener_cb cb 事件触发的回调
void *ptr 回调函数的参数,这个参数可以由用户任意指定,方便在回调函数中使用
unsigned flags 事件的附加标识,代表事件操作
int backlog 网络缓存大小
const struct sockaddr *sa socket地址
int socklen socket地址长度
函数会返回一个新的evconnlistener,如果创建成功,需要使用evconnlistener_free()来释放资源。
(3)event_base_dispatch():启动事件循环和事件分发
这个函数会阻塞当前线程,用户可以在事件回调函数中通过event_base_loopbreak()来中断。如果不希望当前线程被堵塞也可以使用event_base_loop()函数。注意,千万不要在回调函数中清理event_base。
代码示例:
// 创建事件循环 ev_base_ = event_base_new(); if (!ev_base_) { return false; } sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port_); // 创建socket连接回调 ev_listener_ = evconnlistener_new_bind( ev_base_, SConnListenerCb, this, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, this->backlog_, (sockaddr *)&sin, sizeof(sin)); if (!ev_listener_) { return false; } while (!quit_) { event_base_loop(ev_base_, EVLOOP_NONBLOCK); this_thread::sleep_for(chrono::milliseconds(1)); } evconnlistener_free(ev_listener_); event_base_free(ev_base_);