项目当中用到了libevent,遂分析之,本次分析的版本是libevent-2.0.21-stable。libevent是一个网络库,在分析它之前,先小结一下服务端网络编程架构:
int _tmain(int argc, _TCHAR* argv[]) { //libevent初始化 struct event_base *base = event_base_new(); //socket初始化 evconnlistener_new_bind //设置回调函数 evconnlistener_set_error_cb(listener,accept_error_cb); //进入循环 event_base_dispatch(base); return 0; }以上是一个服务器程序的主要框架,剩下要做得事情就是当某个网络事件发生时,获取相应的句柄,建立或者获取相应的缓冲区进行操作。笼统来说,Libevent就是干这事的。它将以上的代码封装起来,提供一系列回调让程序员将主要精力从网络通讯的细节中解放出来,放在主要业务逻辑上。它另外统一了定时器与信号处理函数,使之等同于网络事件。
经过libevent的封装之后,以上代码变成
static void echo_read_cb(struct bufferevent* bev, void *ctx) { } //accept回调 static 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); struct bufferevent* bev = bufferevent_socket_new(base,fd, BEV_OPT_CLOSE_ON_FREE); //设置读写回调 bufferevent_setcb(bev,echo_read_cb,echo_write_cb,echo_event_cb,NULL); bufferevent_enable(bev,EV_READ|EV_WRITE); } int _tmain(int argc, _TCHAR* argv[]) { //libevent初始化 struct event_base *base = event_base_new(); //socket初始化 struct evconnlistener *listener = evconnlistener_new_bind(base,accept_conn_cb.....) //设置回调函数 evconnlistener_set_error_cb(listener,accept_error_cb); //进入循环 event_base_dispatch(base); return 0; }libevent是用C语言写的,但却又是面向对象的。因此可以认为base是一个对象实例,一个线程只能有一个base。
第一段代码中的for(;;)循环被封入了event_base_dispatch中。循环里的事件调用被设置成了一个个的回调函数。
至此,我们感兴趣的代码大概会分布在:
1,初始化,及分配的event_base对象。它应该是整个libevent的核心。
2,设置callback的函数,以及callback回调的时机。
3,event_base_dispatch的循环。
还有,根据资料它还提供了输入缓冲及输出缓冲。这个应该也是比较有意思的一部分。
分析代码之前,最重要的是要知道在找什么,那样才不会迷失在代码的海洋中。初见到此为止,下篇开始分析libevent的初始化,以及event_base对象。