赞
踩
目录
libevent是一个轻量级的开源高性能网络库,基于"事件"异步通信模型。适用于windows、linux、bsd等多种平台(跨平台),内部使用select、epoll、kqueue等系统调用管理事件机制。著名分布式缓存软件memcached也是libevent based,而且libevent在使用上可以做到跨平台,而且根据libevent官方网站上公布的数据统计,似乎也有着非凡的性能。
- //在本地目录解压安装包
- tar zxvf libevent-2.1.8-stable.tar.gz
-
- //到解压好的安装包文件夹下执行安装过程
- cd libevent-2.1.8-stable/
-
- //执行./configure
- ./configure
- make
- sudo make install
/usr/local/include
/usr/local/lib
gcc helloworld.c -o helloworld -l event //去掉lib和后缀.so(动态库)就是库名
- struct event_base {
- const struct eventop *evsel;
- void *evbase;
- int event_count; /* counts number of total events */
- int event_count_active; /* counts number of active events */
- int event_gotterm; /* Set to terminate loop */
- int event_break; /* Set to terminate loop immediately */
- /* active event management */
- struct event_list **activequeues;
- int nactivequeues;
- /* signal handling info */
- struct evsignal_info sig;
- struct event_list eventqueue;
- struct timeval event_tv;
- struct min_heap timeheap;
- struct timeval tv_cache;
- };
event_base_new()函数分配并且返回一个新的具有默认设置的event_base。函数会检测环境变量,返回一个到event_base的指针。若发生错误,则返回NULL。选择各种方法时,函数会选择OS支持的最快方法
- struct event_base *event_base_new(void);
-
- struct event_base *base = event_base_new();
- /*
- base: event_base_new() 返回值
- fd: 绑定到event上的文件描述符
- what:对应所需执行的读、写、异常操作
- EV_READ
- EV_WRITE
- EV_PERSIST持续触发 (可以理解为:while(read()) 或 while(write()))
- cb:一旦事件满足监听条件,回调的函数
- typedef void(*event_callback_fn)(evutil_socket_t fd, short, void *)
- arg:回调的函数的参数
- 返回值:成功创建的event
- */
- struct event *event_new(struct event_base *base, evutil_socket_t fd, short what,
- event_callback_fn cb, void *arg);
- /*
- ev: event_new() 函数返回的事件
- tv:为NULL,不会超时。意为:一直等到事件被触发,回调函数会被调用
- 为非0。等待期间,检查事件没有被触发,时间到,回调函数依旧会被调用
- */
- int event_add(struct event *ev, const struct timeval *tv);
- //ev:event_new()函数返回的事件
- int event_del(struct event *ev);
- //成功:0, 失败:-1
- int event_free(struct event *ev);
未决:有资格被处理,但还没有被处理
非未决:没有资格处理
event_new --> event --> 非未决 --> event_add -->未决 --> dispath() && 监听事件被触发 --> 激活态 --> 执行回调函数 --> 处理态 --> 非未决 event_add && EV_PERSIST --> 未决 --> event_del --> 非未决
- #include <event2/bufferevent.h>
-
- 原理:bufferevent有两个缓冲区:也是队列实现,缓冲区内部的数据只能读一次,读完就没有了。
- 由于使用fifo,数据先进先出
读:有数据 --》 读回调函数read_cb()被调用 --》 使用bufferevent_read() --》 读数据
写:使用bufferevent_write() --》 向写缓冲中写数据 --》 该缓冲区有数据自动写出 --》 写完,回调函数write_cb()被调用
- /*
- 创建:
- base:event_base_new 函数的返回值
- fd: 跟bufferevent绑定的文件描述符。类比 event_new()
- options:
- BEV_OPT_CLOSE_ON_FREE:释放 bufferevent 时关闭底层传输端口。这将关闭底层
- 套接字,释放底层bufferevent 等。
- BEV_OPT_THREADSAFE:自动为 bufferevent 分配锁,这样就可以安全地在多个线程
- 中使用 bufferevent。
- BEV_OPT_DEFER_CALLBACKS:设置这个标志时,bufferevent 延迟所有回调,如上所述
- BEV_OPT_UNLOCK_CALLBACKS:默认情况下,如果设置 bufferevent 为线程安全的,则
- bufferevent 会在调用用户提供的回调时进行锁定。设置这个选项会让 libevent在执行
- 回调的时候不进行锁定。
- */
- struct bufferevent *bufferevent_socket_new(struct event_base *base,
- evutil_socket_t fd, enum bufferevent_options options);
-
-
- /*
- 释放:
- bev: bufferevent_socket_new()的返回值
- */
- void bufferevent_free(struct bufferevent *bev);
- /*
- bufev: bufferevent_socket_new() 返回值
- readcb: 设置bufferevent读缓冲, 对应回调
- writecb: 设置bufferevent写缓冲, 对应回调 ,可传NULL
- eventcb: 设置事件回调。 也可传NULL
- cbarg:上述回调函数使用的参数
- */
- void bufferevent_setcb(struct bufferevent *bufev,
- bufferevent_data_cb readcb,
- bufferevent_data_cb writecd,
- bufferevent_event_cb eventcb,
- void *cbarg);
readcb对应的回调函数
- typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);
-
- 如:
- void read_cb(struct bufferevent *bev, void *arg){
- ......
- bufferevent_read(); //读数据,类似read()的作用
- }
-
- 读数据:从bufferevent输入缓冲区 中 移除数据
-
- //通常用在readcb中,替代read()
- size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
-
- //常用在bufferevent_read之后,替代write()
- int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
writecb对应的回调函数
- 非常不使用!!!!
- 如:
- void write_cb(struct bufferevent *bev, void *arg){
- ......
- }
eventcb对应的回调函数
- typedef void(*bufferevent_event_cb)(struct bufferevent *bev,
- short events, void *ctx);
events:
BEV_EVENT_READING:读取操作时发生某事件,具体是哪种事件请看其他标志。 BEV_EVENT_WRITING:写入操作时发生某事件,具体是哪种事件请看其他标志。 BEV_EVENT_ERROR : 操 作 时 发 生 错 误 。 关 于 错 误 的 更 多 信 息 , 请 调 用 EVUTIL_SOCKET_ERROR()。
BEV_EVENT_TIMEOUT:发生超时。
BEV_EVENT_EOF:遇到文件结束指示。
BEV_EVENT_CONNECTED:请求的连接过程已经完成。
默认:新建的bufferevent写缓冲是enable的。而,读缓冲是disable的
- //通常用来启用bufferevent的read缓冲
- void bufferevent_enable(struct bufferevent *bufev, short events);启用缓冲区
-
- //events: EV_READ、EV_WRITE、EV_READ|EV_WRITE
- void bufferevent_disable(struct bufferevent *bufev, short events); 禁用缓冲区
-
- //获取缓冲区的禁用状态,需要借助& 来得到
- short bufferevent_get_enabled(struct bufferevent *bufev);
- /*
- ev: event_new() 函数返回的事件
- tv:为NULL,不会超时。意为:一直等到事件被触发,回调函数会被调用
- 为非0。等待期间,检查事件没有被触发,时间到,回调函数依旧会被调用
- */
- int event_add(struct event *ev, const struct timeval *tv);
- int event_base_dispatch(struct event_base *base);
- /*
- base:event_base_new 函数的返回值
- 成功 :0, 失败 :-1
- 只有event_new 中指定了 EV_PERSIST 才持续触发,否则只触发一次,就跳出循环
- 通常这样:EV_WRITE|EV_PERSIST 、EV_READ|EV_PERSIST
- */
若想在移除所有已注册的事件之间停止活动的事件循环,可以调用两个稍有不同的函数。
- //在指定时间后停止循环 tv:设置超时时间
- int event_base_loopexit(struct event_base *base, const struct timeval *tv);
-
- //立即停止循环
- int event_base_loopbreak(struct event_base *base);
void event_base_free(struct event_base *base);
- //返回:字符指针数组
- const char **event_get_supported_methods(void);
const char * event_base_get_method(const struct event_base *base);
不是所有事件后端都在调用fork()之后可以正确工作。所以,若在使用fork()或者其他相关系统调用启动新进程之后,希望在新进程中继续使用event_base,就需要进行重新初始化。
- /*
- 成功:0,失败:-1
- 使用该函数后,父进程创建的base才能在子进程中生效
- */
- int event_reinit(struct event_base *base);
libevent支持为事件设置多个优先级。然而,event_base默认只支持单个优先级。可以调用event_base_priority_init()设置event_base的优先级数目。
- /*
- 成功时这个函数返回0,失败时返回-1。base是要修改的event_base,n_priorities是要支持的优先级数目,这个数目至少为1.每个新的事件可用的优先级将从0(最高)到n_priorities-1(最低)。
- */
- int event_base_priority_init(struct event_base *base, int n_priorities);
常量 EVENT_MAX_PRIORITIES 表示 n_priorities 的上限。调用这个函数时为 n_priorities 给出更大的值是错误的。
必须在任何事件激活之前调用这个函数,最好在创建event_base后立刻调用。
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <fcntl.h>
- #include <event2/event.h>
-
- //对操作处理函数
- void read_cb(evutil_socket_t fd, short what, void *arg){
- //读管道
- char buf[1024] = {0};
- int len = read(fd, buf, sizeof(buf));
- printf("read event: %s \n", what & EV_READ ? "Yes" : "No");
- printf("data len = %d, buf = %s\n", len, buf);
- sleep(1);
- }
-
-
- //读管道
- int main(int argc, const char* argv[]){
-
- unlink("myfifo");
- //创建有名管道 0664:设置fifo权限
- mkfifo("myfifo", 0664);
-
- //open file
- int fd = open("myfifo", O_RDONLY | O_NONBLOCK);
- if(fd == -1){
- perror("open error");
- exit(1);
- }
-
- //创建个event_base
- struct event_base *base = NULL;
- base = event_base_new();
-
- //创建事件
- struct event* ev = NULL;
- ev = event_new(base, fd , EV_READ | EV_PERSIST, read_cb, NULL);
-
- //添加事件
- event_add(ev, NULL);
-
- //事件循环
- event_base_dispatch(base);
-
- //释放资源
- event_free(ev);
- event_base_free(base);
- close(fd);
-
- return 0;
- }
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <event2/event.h>
-
- //对操作处理函数
- void write_cb(evutil_socket_t fd, short what, void *arg){
-
- //write管道
- char buf[1024] = {0};
- static int num = 0;
- sprintf(buf, "hello,world-%d\n", num++);
- write(fd, buf, strlen(buf)+1);
- sleep(1);
- }
-
- //写管道
- int main(int argc, char *argv[]){
- //open file
- int fd = open("myfifo", O_WRONLY | O_NONBLOCK);
- if(fd == -1){
- perror("open error");
- exit(1);
- }
-
- //写管道
- struct event_base* base = NULL;
- base = event_base_new();
-
- //创建事件
- struct event* ev = NULL;
- //检测的写缓冲区是否有空间写
- //ev = event_new(base, fd, EV_WRITE, write_cb, NULL);
- ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);
-
- //添加事件
- event_add(ev, NULL);
-
- //事件循环
- event_base_dispatch(base);
-
- //释放资源
- event_free(ev);
- event_base_free(base);
- close(fd);
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。