libevent反应堆初识

本文深入解析libevent库,涵盖I/O、定时与信号事件,详细阐述事件创建、添加、删除及事件循环机制。同时,介绍bufferevent特性,包括创建、销毁、回调设置及缓冲区控制,探讨客户端与服务器端的TCP连接建立过程。
摘要由CSDN通过智能技术生成

 

libevent中的三种事件:I/O事件、定时事件、信号事件

 

 

libevent库

开源。精简。跨平台(Windows、Linux、maxos、unix)。专注于网络通信。

源码包安装: 参考 README、readme

./configure 检查安装环境 生成 makefile

make 生成 .o 和 可执行文件

sudo make install 将必要的资源cp置系统指定目录。

进入 sample 目录,运行demo验证库安装使用情况。

编译使用库的 .c 时,需要加 -levent 选项。

库名 libevent.so --> /usr/local/lib 查看的到。

特性:基于“事件”异步通信模型。--- 回调。

 

libevent框架:

常规事件

  1. 创建 event_base (乐高底座) struct event_base *event_base_new(void);
  2. 创建 事件evnet 常规事件 event --> event_new();

bufferevent --> bufferevent_socket_new();

  1. 将事件 添加到 base上 int event_add(struct event *ev, const struct timeval *tv)
  2. 循环监听事件满足 int event_base_dispatch(struct event_base *base);
  3. 释放 event_base event_base_free(base);

 

  • 创建事件event: struct event *ev;

struct event *event_new(struct event_base *base,evutil_socket_t fd,short what,event_callback_fn cb; void *arg);

base: event_base_new()返回值。

fd: 绑定到 event 上的 文件描述符

what:对应的事件(r、w、e)

EV_READ 一次 读事件

EV_WRTIE 一次 写事件

EV_PERSIST 持续触发。结合 event_base_dispatch 函数使用,生效。

cb:一旦事件满足监听条件,回调的函数。

    • 回调函数:typedef void (*event_callback_fn)(evutil_socket_t fd, short, void *)

arg: 回调的函数的参数。

返回值:成功创建的 event 添加事件到 event_base

 

    • 添加事件:int event_add(struct event *ev, const struct timeval *tv);

ev: event_new() 的返回值。 tv:NULL

 

    • 删除事件:int event_del(struct event *ev);

ev: event_new() 的返回值。

销毁事件 int event_free(struct event *ev); ev: event_new() 的返回值。

 

未决和非未决:

非未决: 没有资格被处理

未决: 有资格被处理,但尚未被处理

event_new --> event ---> 非未决 --> event_add --> 未决 --> dispatch() && 监听事件被触发 --> 激活态 --> 执行回调函数 --> 处理态 --> 非未决 event_add && EV_PERSIST --> 未决 --> event_del --> 非未决

 

 

注意的几点:

        1. int event_reinit(struct event_base *base);用于fork之后子进程重新初始化事件反应堆
        2. 向关闭的socket中写入数据会触发SIGPIPE信号,导致服务器异常退出,所以需要signa(SIGPIPE,SIG_IGN)忽略该信号
        3. 需要将socket设置为非阻塞态evutil_make_socket_nonblocking();
        4. 设置地址复用 evutil_make_listen_socket_reuseable();
        5. 如果添加事件是设置了timeval,则时间到时会触发EV_TIMEOUT信号

        1.  

 

 

 

带缓冲区的事件 bufferevent --- 只能适用于tcp流式传输

#include <event2/bufferevent.h>

read/write 两个缓冲. 借助队列.读走数据即不存在数据

 

优点:与通常的事件在底层传输端口已经就绪,可以读取或者写入的时候执行回调不同的是,bufferevent 在读取或者写入了足够量的数据之后调用用户提供的回调。(水位的设置)

 

1、创建、销毁bufferevent:

struct bufferevent *ev;

创建 struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, enum bufferevent_options options);

base: event_base

fd: 封装到bufferevent内的 fd

options:BEV_OPT_CLOSE_ON_FREE

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

 

销毁 void bufferevent_socket_free(struct bufferevent *ev);

给bufferevent设置回调:

对比event: event_new( fd, callback ); event_add() -- 挂到 event_base 上。

bufferevent_socket_new(fd) bufferevent_setcb( callback )

 

2、给bufevent设置回调函数:

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: 设置 bufferevent 读缓冲,对应回调 read_cb{ bufferevent_read() 读数据 }

writecb: 设置 bufferevent 写缓冲,对应回调 write_cb { } -- 给调用者,发送写成功通知。可以NULL

eventcb: 设置 事件回调。 也可传NULL

typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx);

void event_cb(struct bufferevent *bev, short events, void *ctx)

{

。。。。。

}

events: BEV_EVENT_CONNECTED

cbarg: 上述回调函数使用的 参数。

 

各个回调函数调用的时机: bufferevent_trigger()函数可以调用任意回调函数

1)read ------ 当缓冲区有东西可读的时候

2)write ----- 当客户端第一次连接上来的时候(此时客户端发起连接的是connect而不是bufferevent_socket_connect)或者当bufferevent_write被调用的时候

3)event ---- 当客户端退出或者有超时事件的时候

 

bufevent_write()操作还是会调用write事件

 

read 回调函数类型:

typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void*ctx);

void read_cb(struct bufferevent *bev, void *cbarg )

{

…..

bufferevent_read(); --- 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);

 

3、启动、关闭 bufferevent的缓冲区:

void bufferevent_enable(struct bufferevent *bufev, short events); 启动

events: EV_READ、EV_WRITE、EV_READ|EV_WRITE

默认:write 缓冲是 enable、read 缓冲是 disable

bufferevent_enable(evev, EV_READ); -- 开启读缓冲。

 

4、水位的设置

    • 读端:默认值是0,表示无限制。
    • 写端:只要低于最低水位即可写入到缓冲区中,高水位不必关注,置0即可。

 

 

客户端

连接客户端:

socket();connect();

int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);

bev: bufferevent 事件对象(封装了fd)

address、len:等同于 connect() 参2/3

 

注意: 如 果 使 用 bufferevent_socket_connect() 发 起 连 接 , 将 只 会 收 到

BEV_EVENT_CONNECTED 事件。如果自己调用 connect(),则连接上将被报告为写入事

 

  • write_cb回调函数真的很鸡肋!!没啥用处,因为它只有调用bufferevent_trigger()或者当bufferevent_write()使用之后才会调用,所以当数据都发送完成了,才调用write_cb。。。

 

创建监听服务器:

------ socket();bind();listen();accept();

struct evconnlistener * listner

struct evconnlistener *evconnlistener_new_bind (

struct event_base *base,

evconnlistener_cb cb,

void *ptr,

unsigned flags,

int backlog,

const struct sockaddr *sa,

int socklen);

base: event_base

cb: 回调函数。 一旦被回调,说明在其内部应该与客户端完成, 数据读写操作,进行通信。

ptr: 回调函数的参数

flags: LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE

backlog: listen() 2参。 -1 表最大值

sa:服务器自己的地址结构体

socklen:服务器自己的地址结构体大小。

返回值:成功创建的监听器。

 

 

释放监听服务器:

void evconnlistener_free(struct evconnlistener *lev);

 

 

服务器端 libevent 创建TCP连接:

  1. 创建event_base
  2. 创建bufferevent事件对象。bufferevent_socket_new();
  3. 使用bufferevent_setcb() 函数给 bufferevent的 read、write、event 设置回调函数。
  4. 当监听的 事件满足时,read_cb会被调用, 在其内部 bufferevent_read();读
  5. 使用 evconnlistener_new_bind 创建监听服务器, 设置其回调函数,当有客户端成功连接时,这个回调函数会被调用。
  6. 封装 listner_cb() 在函数内部。完成与客户端通信。
  7. 设置读缓冲、写缓冲的 使能状态 enable、disable
  8. 启动循环 event_base_dispath();
  9. 释放连接。 客户端端 libevent 创建TCP连接:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值