简介
由于本项目是纯异步的,而对于大量 socket 连接,使用 select 并不高效。(参见我的另一篇博文:epoll简介)
事实上,大部分系统提供了处理大量 socket 连接的解决方案:
Linux 下的 epoll()
BSD 下的 kqueue()
Solaris 下的 evports
Windows 下的 IOCP
由于各个平台使用了不同的接口,所以想编写跨平台的高性能异步程序就需要做一层跨平台封装。此时 Libevent 是一个不错的选择(当然你也可以自己来实现这个事-。-),其最底层 API(event 和 event_base API)为各个平台实现高性能异步程序提供了一致的接口。
一些概念
event:会绑定文件描述符、回调函数并表示一个或者多个条件(例如,文件描述符可以读、写或者超时等)。event 表示的条件如果被触发了,那么 event 会变为活跃的,它绑定的回调函数就会被执行。
event_base: 持有一组 event 并进行事件循环,event_base 会存在一个后端(也叫做方法),常见的后端包括 epoll、kqueue 等。
结构
组件:
evutil 用于抽象不同的平台的网络(基础的)实现;
event、event_base 为 Libevent 的核心,为不同的平台下基于事件的非阻塞 I/O 提供了一套抽象的接口;
bufferevent 对 Libevent 的基于事件的核心的封装。应用程序的读写请求是基于缓冲区的;
evbuffer 为 bufferevent 实现的缓冲区;
evhttp 一个简单的 HTTP client/server 的实现;
evdns 一个简单的 DNS client/server 的实现;
evrpc 一个简单的 RPC 实现;
库:
libevent_core 包括 util、event_base、evbuffer、bufferevent;
libevent_extra 包括 HTTP、DNS、RPC;
libevent 此库由于历史原因而存在,不要使用它;
libevent_pthreads 此库为基于 pthread 的线程和锁的实现;
libevent_openssl 此库通过 openssl 和 bufferevent 提供了加密通讯;
头文件:
所有的公用头文件位于 event2 目录中。
创建和销毁 event_base
event_base 是最基本的,故需要首先被创建。
event_base 结构持有一个 event 集合。如果 event_base 被设置了使用锁,那么它在多个线程中可以安全的访问。但是对 event_base 的循环只能在某个线程中执行。如果希望在多个线程中进行循环,那么应该为每一个线程创建一个 event_base。
event_base 存在多个后端可以选择(我们也把 event_base 后端叫做 event_base 的方法):
select
poll
epoll
kqueue
devpoll
evport
win32
在创建 event_base 时,libevent 会为我们选择最快的后端。
创建 event_base 的函数:
// 创建成功返回一个拥有默认设置的 event base
// 创建失败返回 NULL
struct event_base *event_base_new(void);
// 查看 event_base 实际上使用到的后端
const char *event_base_get_method(const struct event_base *base);
event_base 的释放使用函数:
void event_base_free(struct event_base *base);
事件循环(event loop)
event_base 会持有一组 event。如果我们向 event_base 中注册了一些 event,那么就可以让 libevent 开始事件循环了:
// 指定一个 event_base 并