Libevent官方
学习目标:
掌握libevent封装的框架思想
了解bufferevent特性
掌握bufferevent事件对象创建、销毁。
libevent:
libevent: 是一个用C语言编写的、轻量级的开源高性能事件通知库。(编译时加 -levent)
*libevent特点:
- 事件驱动、高性能
- 轻量级、专注于网络
- 跨平台、支持Windows、Linux、Mac OS等
- 支持多种I/O多路复用技术、epoll、poll、dev/poll、select和kqueue等
- 支持I/O、定时器和信号等事件。
*libevent框架:
创建event_base(头文件event2/event.h)
//原型
struct event_base *event_base_new(void);
//使用
struct event_base *base = event_base_new(void);
创建事件event
- 常规事件创建与销毁
/*常规事件创建
参数:
base:event_base_new()函数返回的事件
fd:绑定到event上的文件描述符
what:EV_READ (一次读事件) EV_WRITE (一次写事件)EV_PERSIST(持续触发)
cb:一旦事件满足监听条件,回调的函数 回调函数原型如下:
typedef void(*event_callback_fn)(evutil_socket_t fd,shrt,void *);
arg:回调函数的参数
*/
struct event *event_new(struct event_base *base,evutil_socket_ fd,short what,event_callback_fn cd,void *arg);
// 销毁
int event_free(struct event *ev);
- 带缓冲区的事件创建 read/write两个缓冲、借助队列。(头文件event2/bufferevent.h)
/*创建
参数:
base:event_base_new()函数返回的事件
fd:封装到bufferevent内的fd
options:BEV_OPT_CLOSE_ON_FREE(只用这一个即可)
返回值:
成功创建的bufferevent事件对象
*/
struct bufferevent *bufferevent_socket_new(struct event_base *base,evutil_socket_ fd enum, bufferevent options options);
/* 销毁
参数:
bufev:bufferevent_socket_new()返回值
*/
void bufferevent_socket_free(struct bufferevent *ev);
/*给bufferevent设置回调
readcb:设置bufferevent读缓冲,对应回调read_cb
weitecb:设置bufferevent写缓冲,对应回调write_cb 给调用者发送写成功通知可为NULL
eventcb:设置事件回调,可为NULL
cbarg:回调函数使用的参数
*/
void bufferevent_setcb(struct bufferevent *bufev,bufferevent_data_cb readbc,bufferevent_data_cb writecb,bufferevent_cb eventcb,void *cbarg);
//read回调函数类型
typedef void (*bufferevent_data_cb)(struct bufferevent *bev,void *cbarg);
void read_bc(struct bufferevent *bev,void *cbarg){
.........
bufferevent_read();
}
//bufferevent_read()函数原型
size_t bufferevent_read(struct bufferevent *bev,void *buf,size_t bufsize);
//write回调函数类型
int bufferevent_write(struct bufferevent *bufev,const void *data,size_t size);
//启动、关闭bufferevent的缓冲区
void bufferevent_enable(struct bufferevent *bufev,short events);
//events: EV_READ\EV_WRETE\EV_READ|EV_WRITE
//默认write缓冲区是enable、read缓冲区是disable
bufferevent_enable(ev,EV_READ);//开启读缓冲
/*连接服务器
参数:
bev:bufferevent 事件对象(封装了fd)
address:地址结构体
addrlen:地址结构体的大小
等同于connect()函数参2,参3
*/
int bufferevent_sokcet_connect(struct bufferevent *bev,struct sockaddr *address,int addrlen);
/*创建监听服务器
参数:
base:event_base返回对象
cb:回调函数,一旦被调用说明在其内部应该与客户端完成数据读写操作,进行通信。
ptr:回调函数的参数
flags:LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE
backlog:listen()2参,-1表最大值
sa:服务器自己的地址结构体
socklen:服务器自己的地址结构体大小
返回值:成功创建的监听器。
*/
struct evconnlistener *listner
struct evconnlistener *evconnlistener_new_bind(struct event_base *base,evconnlistener_cb cb,void *ptr,unsigned flage,int backlog,const struct sockaddr *sa,int socklen);
//listener_cb回调函数原型
void listener_cb(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *sa,int socklen,void *user_data);
//释放监听服务器
void evconnlistener_free(struct evconnlistner *lev);
/*bufferevent清空
iotype:EV_READ | EV_WRITE
state::BEV_NORMAL
*/
int bufferevent_flush(struct bufferevent *bufev,
short iotype, enum bufferevent_flush_mode state);
服务器端libevent创建TCP连接:
- 创建event_base
- 使用evconnlistener_new_bind创建监听服务器,设置其回调函数,当有客户端成功连接时,这个回调函数会被调用
- 封装listener_cb()在函数内部,完成与客户端通信
- 创建bufferevent事件对象,bufferevent_socket_new()
- 使用bufferevent_setcb()函数给bufferevent的read、write、event设置回调函数
- 设置读缓冲、写缓冲的使能状态
- 当监听的事件满足时,read_cb会被调用,在器内部bufferevent_read()读
- 启动循环event_base_dispath()
- 释放连接
将事件添加到base上
/*
参数:
ev:event_new()函数返回的事件
tv:为NULL,不会超时:一直等到事件被触发,回调函数会被调用。为非0时,等待期间检查事件有没有被触发,时间到回调函数依旧会被使用
*/
int event_add(struct event *ev,const struct timeval *tv);
将事件从base上摘下
int event_del(struct event *ev);
循环监听事件满足
/*
参数:
base:event_base_new()函数返回的事件
返回值
成功:0
失败:-1
*/
int event_base_dispatch(struct event_base *base);
只有event_new种指定了EV_PERSIST才持续触发,否则只触发一次,就跳出循环
释放event_base
//原型
void event_base_free(struct event_base *base);
//使用
event_base_free(base);
未决和非为决
未决:有资格被处理,但尚未被处理。
非为决:没有资格被处理
event_new→event→非为决→event_add→未决→dispatch() && 监听事件被触发→激活态→执行回调函数→处理态→非为决event_add && EV_PERSIST→未决→event_del→非为决