高并发学习分享日记1
今天起我将不定期更新高并发网络学习知识,用以记录和分享我关于高并发相关的知识点
开源网络高并发工具libevent - 框架介绍
linux下如果需要实现高并发的tcp通信,第一反应一定是epoll,但如果开发者对epoll不是很了解,或者开发平台不是linux,那么我们就要介绍到今天的主角:libevent。
libevent 1、libevent不是一个函数方法,而是一个开源的三方库,libevent应用广泛,不乏其他框架,例如缓存数据库(memcached),其中用以实现高并发网络操作的网络模块就是调用libevent现有的API接口。 2、llibevent中封装着除select、poll、epoll等常用IO转接函数外还有一些其他的IO转接函数用以实现socket网络通信。 3、libevent所有的事件操作(读事件、写事件等)均回调函数实现,使其代码精简且高效。 libevent的安装和使用 1、下载: 官方网址:http://libevent.org 下载源码学习,建议使用1.4.x-stable版本。 使用建议使用最新稳定版。 2、安装 linux:tar zxvf libevent-xxx-stable.tar.gz cd libevent-xxx-stable. ./configure --perfix==/usr/xxx #指定安装目录 如果只是./configure则为默认安装目录 make sudo make install cd sample 执行其中任意一个简单demo 例:./hello-world 新启一个窗口:nc 127.1 9995 如果可以收到"Hello, world!",则说明安装成功 windows:目前暂未用到,如果有哪位大佬知道,请评论区补充。 3、编译和链接 常用头文件:<event2/event.h> <event2/listener.h> 链接:gcc .c -o ProgramName -levent 4、使用方法 4.1、 创建一个事件处理框架 - event_base结构 event_base结构中中封装了Socket通信中的各个IO转接函数,且当中存在一个事件集,可以检测那些事件是激活的,相当于epoll红黑树的树根,创建了event_base结构后,他就提供一种用户检测事件是否就绪的”方法“。(使用者需要做的事情就是创建事件并丢入其中,既后续步骤) 创建event_base:struct event_base event_base_new(void); // 其中有消息循环但是没有启动 创建失败:返回NULL 注意:如果使用中存在进程,如在主进程中创建了event_base* base类型对象,则子进程中也可以使用,但必须在子进程中重新初始化event_reinit(base); 4.2、创建一个事件 不带缓冲去的事件:struct event* event_new(struct event_base base, evutil_socket_t fd, short what, event_callback_fn cb, void arg); event_callback_fn cb:事件回调处理动作: typefef void (event_callback_fn)(evutil_socket_t, short, void); evutil_socket_t fd:文件描述符 int类型,给回调函数event_callback_fn cb中的evutil_socket_t传参 short what: 事件类型如下,给回调函数event_callback_fn cb中的short传参 #define EV_READ 0x02 // 对应epollin 如果使用event_base_dispatch循环,此参数创建的事件读完一次后会被从框架中删除,继续进入非未决状态 #define EV_WRITE 0x04 // 对应epollout 如果使用event_base_dispatch循环,此参数创建的事件读完一次后会被从框架中删除,继续进入非未决状态 #define EV_SIGNAL 0x08 // 信号相关操作 #define EV_PERSIST 0x10 // 持续触发 如果使用event_base_dispatch循环,此参数创建的事件读完一次后会被从框架中删除,然后再添加进去 #define EV_ET 0x20 // 对应epoll边沿模式 void* arg:给回调函数event_callback_fn cb中的void传参 注:调用event_new()函数之后, 新事件处于已初始化和非未决状态。 非未决:没有资格被处理 未决:有资格被处理但还未处理 4.3、将事件添加到事件处理框架中 创建事件框架和事件后并不能对事件进行操作,必须将其添加到事件框架后才能开始检测,因此使用以下函数进行添加: int event_add(struct event *ev, const struct timeval *tv);成功返回0,失败返回-1 tv = NULL :事件被触发,对应的回调才会被调用 tv = {0,100}:如果设置了时间,即使该时间段内检测的事件没有被触发,时间到达后回调还是会调用。 4.4、将事件从事件处理框架中删除 方法1:int event_del(struct event ev);对已经初始化的事件将使其成为非未决和非激活的。如果事件不是未决的或者激活的,调用将没有效果。成功时函数返回 0,失败时返回-1。 方法2:使用event_new创建事件时,short what参数不使用持续触发,既再循环触发一次事件后自动拆除事件框架。 4.5、开始事件循环:event_base_dispatch(struct event_base base)和event_base_loop(struct event_base base, int flags) event_base_loop:event_base_loop(struct event_base* base, int flags):正常退出返回0,失败返回-1 int flags:可以指定事件循环的状态 #define EVLOOP_ONCE 0x01 // 事件只会被触发一次,事件没有被触发, 阻塞等 #define EVLOOP_NONBLOCK 0x02 // 非阻塞 等方式去做事件检测,不关心事件是否被触发了 #define EVLOOP_NO_EXIT_ON_EMPTY 0x04 // 没有事件的时候, 也不退出轮询检测 event_base_dispatch:event_base_dispatch(struct event_base* base):等同于没有设置标识的event_base_loop(),将一直运行到没有注册事件或调用event_base_loopbreak()活event_base_loopexit()为止。 event_base_loopexit: int event_base_loopexit(struct event_base *base, const struct timeval tv); //如果 event_base 当前正在执行激活事件的回调 ,它将在执行完当前正在处理的事件后立即退出。 struct timeval {long tv_usec; long tv_sec; }; // 用来设置设置多长事件后退出这个循环,比如10s后发现消息事件正在执行,则等带执行完毕后退出。 event_base_loopbreak:int event_base_loopbreak(struct event_base base); // 让event_base 立即退出循环 两个循环都是退出成功0,退出失败-1 4.6、释放事件资源:不带缓冲区的 void event_free(struct event event); 4.7、释放框架资源:释放event_base:event_base_free(struct event_base base);
|