一、基础介绍
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 #查看是否已装pythonwhereis 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_basestruct 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_baseevent_base_free();
-
相关函数(了解即可)
const char **event_get_supported_methods(void); //查看支持哪些多路I/O,返回的是数组const char * event_base_get_method(const struct event_base *base); //查看当前用的 多路I/Oint event_reinit(struct event_base *base); //fork()后用来重新初始化子进程中父进程的event_bade,这样父进程创建的 base 才能在子进程中生效。成功:0,失败: -1.
相关函数demo
四、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_baseev :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() 的返回值。创建事件函数的返回值
常规事件的 未决态 和 非未决态:
常规事件demo
五、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)PARAMETERbase :event_basefd :封装到bufferevent内的 fdoptions :BEV_OPT_CLOSE_FREE //释放bufferevent 时关闭底层传输端口。关闭底层套接字,释放底层bufferevent等。2)REATURN VALUE成功创建的 bufferevent 事件对象。2.释放 buffereventvoid 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)PARAMETERbufev :bufferevent_socket_new()函数的返回值。readcb :读缓冲对应的回调,自己封装,在其内部读数据。【注意】使用bufferevent——read()读,而不是read()。 writecb :写缓冲对应的回调,不用的话,传 NULL 即可。//给调用者发送写成功通知。eventcb :设置其他事件回调。可传 NULLcbarg :上述回调函数用的参数2)回调函数定义: 1.bufferevent_data_cb //writecb 、readcb 读写回调typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events,void *ctx)1)PARAMETERbev :创建的 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_WRITEshort 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、32. 服务器创建监听器#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.PARAMETERbase : 创建的 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 的 lenptr :外部 ptr 传递进来值//回调函数由框架自行调用。3.释放创建的监听器void evconnlistener_free(struct evconnlistener *lev); //释放创建的监听器