一、基础介绍
libevent库:
开源。精简。跨平台(Windows、Linux、macos、unix)。专注于网络通信。
libevent-1.4.14 最旧版的适合学习,代码比较基础
libevent-2~ 新版的,加了很多新东西,较难理解,不适合看源码。
二、源码安装(参考 README文件)
1.安装
put C:\Soft\libevent-2.1.12-stable.tar.gz /root/usr/local/src # 上传
tar -zxvf libevent-2.1.12-stable.tar.gz # 解压
cd libevent-2.1.12-stable #进入压缩目录
./configure # 配置
make # 编译
sudo make install # 安装
2.测试
# 进入sample目录
cd libevent-2.1.12-stable/sample
# gcc 编译
gcc hello-world.c -o hello-world -levent #hello-world.c 本质是一个服务器,输出给客户端 hello world
# 执行
./hello-world
# 另起一个中端 执行 ,显示出 hello world
nc 127.0.0.1 9995
-
./configure 出错
解决方案:ubuntu 平台 sudo apt install libssl-dev
-
make 出错
解决方案:
sudo proxychains apt-get install python3.8 #安装python, python3 --version #查看是否已装python3 python --version #查看是否已装python whereis python3 #查找python3的安装位置: whereis python #查找python的安装位置: #系统自带的脚本会以/usr/bin/python的方式直接调用老版本的python,如未安装低版本python就用下面方法建立软连接 sudo ln -s /usr/bin/python3 /usr/bin/python #创建python3 的软连接到 python
-
./hello-world 出错
解决方案:#将没找到的 libevent-2.1.so.7 库软连接到 ldd 默认扫描的目录 /usr/lib 下 sudo ln -s /usr/local/lib/libevent-2.1.so.7 /usr/lib/libevent-2.1.so.7
三、libevent框架——基础
libevent 基于 “事件” 异步通信模型。
--- 主要是利用回调机制
-
libevent 框架基础
#include <event2/event.h> 1.创建 event_base struct event_base *event_base_new(void); struct event_base *base = event_base_new(); 2.创建 事件event(两种) 常规事件 event --> event_new(); //常规事件 不带缓冲区(不常用) bufferevent --> bufferevent_socket_new() //带缓冲区的事件 (常用) 3.将事件 添加到 event_base 上 int event_add(struct event *ev, const struct timeval *tv) 4.循环监听事件满足 //启动循环 若满足绑定的事件 就触发 常用: int event_base_dispatch(struct event_base *base); //持续循环 若满足事件就触发 成功: 0, 失败: -1. 只有event_new() 中指定了 EV_PERSIST 才持续触发,否则只触发一次就跳出循环。 通常:EV_WRITE | EV_PERSIST、EV_READ|EV_PERSIST 不常用: int event_base_loopexit(struct event_base *base,const struct timeval *tv);//在指定时间后停止循环,但在规定时间内仍循环触发 int event_base_loopbreak(struct event_base *base); //立即停止循环 5.释放 event_base event_base_free();
-
相关函数(了解即可)
const char **event_get_supported_methods(void); //查看支持哪些多路I/O,返回的是数组 const char * event_base_get_method(const struct event_base *base); //查看当前用的 多路I/O int event_reinit(struct event_base *base); //fork()后用来重新初始化子进程中父进程的event_bade,这样父进程创建的 base 才能在子进程中生效。 成功:0,失败: -1.
四、libevent框架——常规事件
-
常规事件
1.创建事件 struct event *ev; struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, event_callback_fn cb, void *arg); 1)PARAMETER: base :event_base_new()返回值 fd :绑定到 event 的文件描述符 what :对应的事件(r、w、e) EV_READ 一次 读事件 EV_WRITE 一次 写事件 EV_PERSIST 持续触发。结合 event_base_dispatch 函数使用,生效。 cb :一旦事件满足监听条件,回调的函数。 typedef void (*event_callback_fn)(evutil_socket_t fd, short, void *) arg :回调函数的参数 2)RETURN VALUE 成功创建的 event. 2.事件的添加、摘下、销毁 int event_add(struct event*ev, const struct timeval *tv); //添加事件到 event_base ev :event_new()的返回值。创建事件函数的返回值 tv :NULL,不会超时。等待事件被触发,就调用回调函数 非0,等待期间,检查事件没有被触发,时间到,回调函数依旧会被调用。 int event_del(struct event *ev); //从 event_base 上摘下事件 ev :event_new() 的返回值。创建事件函数的返回值 int event_free(struct event *ev); //销毁event_new()创建的事件 ev :event_new() 的返回值。创建事件函数的返回值
常规事件的 未决态 和 非未决态:
五、libevent框架——带缓冲区事件及网络通信
-
带缓冲区事件
带缓冲区事件裂解里截图理解图:
#include <event2/bufferevent.h> 1.创建 缓冲区事件 bufferevent //和常规event相比,创建时未直接设置回调函数 struct bufferevent *ev; struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd,enum bufferevent_options options); 1)PARAMETER base :event_base fd :封装到bufferevent内的 fd options :BEV_OPT_CLOSE_FREE //释放bufferevent 时关闭底层传输端口。关闭底层套接字,释放底层bufferevent等。 2)REATURN VALUE 成功创建的 bufferevent 事件对象。 2.释放 bufferevent void bufferevent_free(struct bufferevent *bev); bev :bufferevent_socket_new 的返回值。 3.给 bufferevent 设置回调 void bufferevent_setcb(struct bufferevent *bufev ,bufferevent_data_cb readcb ,bufferevent_data_cb writecb ,bufferevent_event_cb eventcb, void *cbarg); 1)PARAMETER bufev :bufferevent_socket_new()函数的返回值。 readcb :读缓冲对应的回调,自己封装,在其内部读数据。 【注意】使用bufferevent——read()读,而不是read()。 writecb :写缓冲对应的回调,不用的话,传 NULL 即可。//给调用者发送写成功通知。 eventcb :设置其他事件回调。可传 NULL cbarg :上述回调函数用的参数 2)回调函数定义: 1.bufferevent_data_cb //writecb 、readcb 读写回调 typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events,void *ctx) 1)PARAMETER bev :创建的 bufferevent。 events :不同标志位,代表不同的事件。 EV_EVENT_READING :读取操作时发生某事件,具体是哪种事件,看其他标志。 BEV_EVENT_WRITING :写入操作时发生某事件,具体是哪种事件请看其他标志。 BEV_EVENT_ERROR :操作时发生错误。关于错误的更多信息,调用 EVUTIL_SOCKET_ERROR()。 BEV_EVENT_TIMEOUT :发生超时。 BEV_EVENT_EOF :遇到文件结束指示。 【常用】 BEV_EVENT_CONNECTED :请求的连接已完成,实现客户端时可用。【常用】 2)应用 void read_cb(struct bufferevent *bev, void *ctx) { ...... bufferevent_read() //读数据,类似 read() bufferevent_write() //写数据,类似 write() } 3)bufferevent_read()、bufferevent_write()原型: size_t bufferevent_read(struct bufferevent *bufev,void *data, size_t size); int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size); 2.bufferevent_event_cb //eventcb回调 typedef void (*bufferevent_event_cb)(struct bufferevent *ev, short events, void *ctx); 1)PARAMETER 和上述 bufferevent_event_cb 的一致。 4.禁用、启用缓冲区 默认:新建的 bufferevt 【写缓冲是 enable的】。而, 【读缓冲是disable的】。 void bufferevent_enable(struct bufferevent *bufev, short events); //启用缓冲区, 通常用来启用 bufferenvet 的 read 缓冲。 void bufferevent_disable(struct bufferevent *bufev,short events); //禁用 events :EV_READ、EV_WRITE、EV_READ|EV_WRITE short bufferevent_get_enabled(struct bufferevent *bufev); //获取缓冲区禁用状态,借助 & 操作。
-
带缓冲区事件的网络通信
1. 客户端连服务器 int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address,int addrlen); bev :bufferevent 事件对象(封装了 fd) address、len:等同于 connect()的参2、3 2. 服务器创建监听器 #include <event2/listener.h> //千万别忘了这个 1)struct evconnlistener * evconnlistener_new(struct event_base *base , evconnlistener_cb cb , void *ptr ,unsigned flags, int backlog, evutil_socket_t fd); //不常用,了解即可 2)struct evconnlistener *evconnlistener_new_bind(struct event_base *base,evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen); //相当于socket()、bind()、listen()、accept()的作用。 1.PARAMETER base : 创建的 event_base 的返回值 cb :回调函数 ptr :回调函数的参数 flags :可识别的标志。 可以用 | 设置多个。 LEV_OPT_CLOSE_ON_FREE //释放 bufferevent 时关闭底层传输端口。 LEV_OPT_REUSEABLE //端口复用。 backlog :listen()参2。 -1 代表最大值。 sa :服务器自己的地址结构体 len :服务器自己的结构体的大小 2.RETURN VALUE 成功:创建的监听器。 3)evconnlistener_new_bind()中回调函数类型 typedef void (*evconnlistener_cb)(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *addr, int len,void *ptr) listener :evconnlistener_new_bind()的返回值 sock :用于通信的文件描述符 addr :客户端的IP + 端口 len :addr 的 len ptr :外部 ptr 传递进来值 //回调函数由框架自行调用。 3.释放创建的监听器 void evconnlistener_free(struct evconnlistener *lev); //释放创建的监听器