本文是关于libevent库第一篇博文,主要由例子来说明如何利用该库。后续博文再深入研究该库原理。

  就如libevent官网上所写的“libevent - an event notification library”,libevent就是一个基于事件通知机制的库,支持/dev/poll、kqueue、event ports、select、poll和epoll事件机制,也因此它是一个跨操作系统的库(支持Linux、*BSD、Mac OS X、Solaris、Windows等)。目前应用该库的有Chromium、Memcached、NTP、tmux等应用。

  libevent 库实际上没有更换select()、poll()或其他机制的基础,而是使用对于每个平台最高效的高性能解决方案,在其实现外加上一个包装器。

  为了实际处理每个请求,libevent 库提供一种事件机制,它作为底层网络后端的包装器。事件系统让为连接添加处理函数变得非常简便,同时降低了底层 I/O 复杂性。这是 libevent 系统的核心。

  libevent 库的其他组件提供其他功能,包括缓冲的事件系统(用于缓冲发送到客户端/从客户端接收的数据)以及 HTTP、DNS 和 RPC 系统的核心实现。

  另外,libevent库非常轻量级,这让我们学习它的源码难度低了不少。关于源码分析具体可参考:

  Libevent源码分析

  libevent源码深度剖析

  如果要生成libevent库的文档,可参考博文使用Doxygen生成libevent document(2.0.15)-- CHM格式。 

回显服务端示例

简易流程

  创建 libevent 服务器的基本方法是,注册当发生某一操作(比如接受来自客户端的连接)时应该执行的函数,然后调用主事件循环event_base_dispatch()。执行过程的控制由 libevent系统处理。注册事件和将调用的函数之后,事件系统开始自治;在应用程序运行时,可以在事件队列中添加(注册)或删除(取消注册)事件。事件注册非常方便,可以通过它添加新事件以处理新打开的连接,从而构建灵活的网络处理系统。

  例如,可以打开一个监听套接字,然后注册一个回调函数,每当需要调用accept()函数以打开新连接时调用这个回调函数,这样就创建了一个网络服务器。下边所示的代码片段说明了这个基本过程:

 1 int main(int argc, char **argv)
 2 {
 3     /* Declare a socket file descriptor. */
 4     evutil_socket_t listenfd;
 5 
 6     /* Setup listening socket */
 7 
 8     /* Make the listen socket reuseable and non-blocking. */
 9     evutil_make_listen_socket_reuseable(listenfd);
10     evutil_make_socket_nonblocking(listenfd);
11 
12     /* Declare an event_base to host events. */
13     struct event_base *base = event_base_new();
14 
15     /* Register listen event. */
16     struct event *listen_event;
17     listen_event = event_new(base, listenfd, EV_READ | EV_PERSIST, do_accetp, (void *)base);
18     event_add(listen_event, NULL);
19 
20     /* Start the event loop. */
21     event_base_dispatch(base);
22 
23     /* End. */
24     close(listenfd);
25 return 0; 26 }

  下边详细介绍上边程序中用到的libevent中的API:

  1)evutil_socket_t 定义于Util.h头文件中,用于跨平台表示socket的ID(在Linux下表示的是其文件描述符),如下所示:

/**
 * A type wide enough to hold the output of "socket()" or "accept()".  On
 * Windows, this is an intptr_t; elsewhere, it is an int. */
#ifdef WIN32
#define evutil_socket_t intptr_t
#else
#define evutil_socket_t int
#endif
View Code

相关文章: