libevent总结(二)-------libevent bufferevent事件

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:49   1894   0

写在前面:

libevent常规事件的总结使用步骤参考:libevent总结(一)-------libevent常规事件

正文:

一、bufferevent 原理:

bufferevent有两个缓冲区:读缓冲区和写缓冲区;分别对应原理如下:
读缓冲:读缓冲中如果有数据-> 会触发我们所写的读所对应的回调函数->回调函数调用 bufferevent_read() ->读数据。
(即bufferevent_read 替代了read函数)
写缓冲:写缓冲中如果有数据->会调用函数 bufferevent_write() ->写数据,发送给对端(即bufferevent_write代了
write函数)。若发送成功,会触发我们所写的写所对应的回调函数来通知我们发送完成了。

二:bufferevent 使用步骤:

第一步:创建event_base
struct event_base * event_base_new(void);

第二步:创建 bufferevent 事件
struct bufferevent * bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options);

参数:base: event_base_new() 创建的对象
fd: 绑定到事件event的文件描述符
options: 一般是0,BEV_OPT_CLOSE_ON_FREE,释放底层的bufferevent。

返回:成功创建的bufferevent 事件对象;

第三步:给bufferevent事件对象设置回调

void bufferevent_setcb(struct bufferevent *bufev,
bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb, void *cbarg)
参数:bufev : bufferevent_socket_new()函数的返回值
readcb : 设置读缓对应的读回调
回调函数类型:typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void
*ctx);//ctx就是cbarg
我们定义的读缓冲的回调函数内部要调用bufferevent_read(),所以要看下这个函数原型:
ev_size_t bufferevent_read(struct bufferevent *bufev, void *data, ev_size_t size);
writecb: 设置写缓冲对应的回调
回调函数类型:typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void
*ctx);//ctx就是cbarg
bufferevent_write()原型:
int bufferevent_write(struct bufferevent *bufev, const void *data, ev_size_t size)

eventcb: 事件回调,一般用来设置错误回调
来看一下事件回调的类型:typedef void (*bufferevent_event_cb)(struct
bufferevent *bev, short what, void *ctx);
what就是事件类型,类型有:
#define BEV_EVENT_READING 0x01 /**< error encountered while reading */
#define BEV_EVENT_WRITING 0x02 /**< error encountered while writing */
#define BEV_EVENT_EOF 0x10 /**< eof file reached */
#define BEV_EVENT_ERROR 0x20/**< unrecoverable error encountered */
#define BEV_EVENT_TIMEOUT 0x40 /**< user-specified timeout reached */
#define BEV_EVENT_CONNECTED 0x80 /**< connect operation finished. */(请求的
连接过程已经完成,实现客户端时可用)

cbarg : 上述回调函数的参数

第四步:缓冲区开启:

注意:新建的bufferevent写缓冲区是enable的,而读缓冲区是disable的,所以读的时候需要使能。

int bufferevent_enable(struct bufferevent *bufev, short event)

参数:
bufev:bufferevent_socket_new()函数的返回值
event:
#define EV_READ 0x02 //读使能
#define EV_WRITE 0x04 //写使能


第五步:缓冲区关闭:

int bufferevent_disable(struct bufferevent *bufev, short event);
参数跟bufferevent_enable()一致。


第六步:释放bufferevent
void bufferevent_free(struct bufferevent *bufev);
参数:bufferevent_socket_new的返回值。

三:客户端和服务器连接和监听:

客户端:
一般的创建socket客户端步骤:socket(); connect();

int bufferevent_socket_connect(struct bufferevent *bev,struct hal_sockaddr *sa, int socklen);

参数:bev:即bufferevent_socket_new()函数的返回值。注意:fd已经封装在 bev对应的类型即bufferevent 里面了。
sa: 即服务器的IP地址结构;
socklen: sa的长度;


服务器:
一般的创建socket服务器步骤: socket();bind();listen();accept();


bufferevent中的evconnlistener_new_bind()函数可替代 socket();bind();listen();accept();这四个函数。
evconnlistener_new_bind()函数原型:
struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
const struct hal_sockaddr *sa, int socklen);
参数:
base:event_base_new()创建的base对象;
cb : listen 回调函数
回调函数的类型:typedef void (*evconnlistener_cb)(struct evconnlistener *listener,
evutil_socket_t sock, struct sockaddr *addr, int len, void *ptr);
回调函数调用的时间:当接收到新连接时(即当有客户端连接时)会调用回调函数;
回调参数:
listener:成功创建的监听器,即evconnlistener_new_bind返回值;
sock: 新接收的套接字,即客户端的套接字;
addr和len;分别是客户端的地址结构和长度;
ptr:外部ptr传进来的参数。

ptr : 回调函数的参数
flags:
LEV_OPT_CLOSE_ON_FREE:如果设置了这个选项,释放连接监听器会关闭底层套接字;
LEV_OPT_REUSEABLE: 端口复用
backlog:int listen(SOCKET sockfd, int backlog);函数的第二个参数,-1,默认最大值;
sa:服务器的IP+port;
socklen: sa的长度

返回值:struct evconnlistener * ,成功创建的监听器。

释放创建成功的监听器对象:void evnlistener_free(struct evconnlistener *lev);

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP