1概念
1.1什么是libevent
- 开源的高性能的事件触发的网络库,内部使用select、poll、epoll等系统调用管理事件机制
- 基于“事件”异步通信模型–>主要依赖于回调函数
1.2优点
- 开源
- 精简
- 跨平台
- 轻量级:专注于网络通信
1.3接口
- 头文件:event2/event.h
- 库:event
- 注意:执行需要指定动态链接库位置:export LD_LIBRARY_PATH=动态链接库位置
2 libevent 框架
-
创建 :event_base;
- struct event_base* pBase = event_base_new();
- struct event evt;
event_new(&evt,pBase,fd,what,cb,arg);
-
创建事件:
- 常规事件event–>event–>event_new();
- 带缓冲区事件:bufferevent–>bufferevent_socket_new();
-
将事件添加到base上
- event_add(pEvent,NULL);
-
循环监听事件满足
- event_base_dispatch(pBase);
- 只有在event_new中指定EV_PERSIST 才持续触发,否则值触发一次就跳出循环
- int event_base_loopexit(struct event_base* base,const struct timeval* tvl)
- 在指定时间跳出循环
- int event_base_loopbreak(struct event_base* base)
- 立即停止循环
- event_base_dispatch(pBase);
-
释放event_base
- event_free(pEvent);
- event_base_free(pBase);
3常规事件event
3.1创建事件
3.1.1函数原型
struct event* event_new(struct event_base* base,evutil_socket_t fd,short what,event_callback_fn cb,void *arg)
3.1.2参数
No. | 参数 | 说明 |
---|---|---|
1 | base | 创建反应器返回指针 |
2 | fd | 套接字的文件描述符 绑定在event上 |
3 | what | 对应的事件(r,w,e) |
4 | cb | 事件绑定的回调函数 一旦满足监听条件 调用回调函数 |
5 | arg | 事件回调函数参数 |
- 对于文件描述符fd,如果没有文件描述符传入-1,例如定时器事件。如果是系统事件,传入对应的事件宏定义。
3.1.2.1事件类型
n | 事件类型 | 说明 | 值 |
---|---|---|---|
1 | EV_TIMEOUT | 超时事件 | 0x01 |
2 | EV_READ | 读事件 | 0x02 |
3 | EV_WRITE | 写事件 | 0x03 |
4 | EV_SIGNAL | 信号事件 | 0x04 |
5 | EV_PERSIST | 持续触发 配合监听函数使用 | 0x05 |
6 | EV_ET | 读写的边沿触发事件 |
3.1.2.2回调函数
typedef void (*event_callback_fn)(evutil_socket_t,short,void*);
- 返回值
- NULL 失败
- 非NULL 事件指针
3.2添加事件
int event_add(struct event* ev,const struct timeval *tv);
3.2.1参数
No. | 参数 | 说明 |
---|---|---|
1 | ev | 事件指针 |
2 | tv | 指定超时时间,NULL表示永不超时:一直等到事件被触发,才会调用回调函数 |
3.2.2返回值
No. | 参数 | 说明 |
---|---|---|
1 | -1 | 失败 |
2 | 0 | 成功 |
3.2销毁事件
void event_free(struct event* ev);// ev 事件指针event_new()的返回值
3.2 删除事件(就是将事件从反应器上拿下来)
int event_del(struct event* ev);// ev 事件指针event_new()的返回值
3.3.1返回值
No. | 参数 | 说明 |
---|---|---|
1 | -1 | 失败 |
2 | 0 | 成功 |
3.5未决和非未决事件
- 未决:有资格被处理 但是还没有被处理
- 非未决:没有资格被处理
- 激活状态(active) 触发事件发生 回调cb
event_new–>event–>非未决–>event_add–>未决–>dispatch–>激活态–>执行回调函数–>处理态–>非未决–>event_add–>未决–>event_del–>非未决
4反应器函数
4.1创建反应器
struct event_base* event_base_new();
- 返回值
- NULL 失败
- 非NULL 反应器指针
4.2释放反应器
void event_base_free(struct event_base* base);//base 反应器指针
4.3 分发事件
int event_base_dispatch(struct event_base* base);// base 反应器指针
- 返回值
- -1 失败
- 0 成功
5示例
5.1read端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<event2/event.h>
#include<errno.h>
void sys_err(const char* str){
perror(str);
exit(1);
}
void read_cb(evutil_socket_t fd,short what,void* arg){
char buf[1024];
int len=read(fd,buf,sizeof(buf));
printf("read from:%s\n",buf);
sleep(1);
}
int main(){
//创建fifo
unlink("testfifo");
mkfifo("testfifo",0644);
//打开fifo的读端
int fd=open("testfifo",O_RDONLY|O_NONBLOCK);
if(fd==-1){
sys_err("open err");
}
//创建Base
struct event_base* base=event_base_new();
//创建事件
struct event *ev=event_new(base,fd,EV_READ|EV_PERSIST,read_cb,NULL);
//将事件加入Base
event_add(ev,NULL);
//循化监听
event_base_dispatch(base);
//销毁base
event_base_free(base);
return 1;
}
5.2write端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<event2/event.h>
#include<errno.h>
void sys_err(const char* str){
perror(str);
exit(1);
}
void write_cb(evutil_socket_t fd,short what,void* arg){
char buf[]="hello libevent";
int len=write(fd,buf,strlen(buf)+1);
sleep(1);
}
int main(){
//打开fifo的读端
int fd=open("testfifo",O_WRONLY|O_NONBLOCK);
if(fd==-1){
sys_err("open err");
}
//创建Base
struct event_base* base=event_base_new();
//创建事件
struct event *ev=event_new(base,fd,EV_WRITE|EV_PERSIST,write_cb,NULL);
//将事件加入Base
event_add(ev,NULL);
//循化监听
event_base_dispatch(base);
//销毁base
event_base_free(base);
return 1;
}