libevent库学习(1)
1、libevent介绍Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大;源代码相当精炼、易读;跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select
一、初识
1、libevent介绍
Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大;源代码相当精炼、易读;跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 I/O,定时器和信号等事件;注册事件优先级。
Libevent 已经被广泛的应用,作为底层的网络库;比如 memcached、 Vomit、 Nylon、 Netchat等等。
2、安装
官网:libevent
我这里用的是2.1.8版本,linux使用的是ubuntu20.4。使用原码安装。
(1)解压
(2)./configure # 检查安装环境 生成 makefile
(3)make # 生成 .o 和 可执行文件
(4)sudo make install # 将必要的资源cp置系统指定目录。
3、检查是否安装成功
进入sample路径下
这里有一些小demo可以测试书否安装成功
这样即表示安装成功。
4、查看安装路径
头文件在include里面
5、框架相关的不常用函数
查看支持哪些多路io
/*************************************************************************
> File Name: 01event.c
> Author: Winter
> Created Time: 2022年02月17日 星期四 20时58分11秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <event2/event.h>
int main(int argc, char* argv[])
{
struct event_base* base = event_base_new(); // 创建base
int i;
const char** buff1;
buff1 = event_get_supported_methods(); // 查看支持哪些多路io
for (i = 0; i < 10; i++) {
printf("buff1[i] = %s\n", buff1[i]);
}
return 0;
}
注意编译时,添加-levent
查看当前使用的多路IO
/*************************************************************************
> File Name: 01event.c
> Author: Winter
> Created Time: 2022年02月17日 星期四 20时58分11秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <event2/event.h>
int main(int argc, char* argv[])
{
struct event_base* base = event_base_new(); // 创建bas
const char *buff2;
buff2 = event_base_get_method(base); // 查看当前使用的多路IO
printf("buff2 = %s\n", buff2);
return 0;
}
二、libevent封装的框架思想
1、libevent框架
1. 创建 event_base (乐高底座)
2. 创建 事件evnet
3. 将事件 添加到 base上
4. 循环监听事件满足
5. 释放 event_base
(1)创建 event_base (乐高底座)
struct event_base *event_base_new(void);
struct event_base *base = event_base_new();
(2)创建 事件evnet
创建事件分为两种:常规事件(event_new)和带缓冲区的事件(bufferevent_socket_new)
常规事件 event --> event_new();
带缓冲区的事件 bufferevent --> bufferevent_socket_new();
(3)将事件 添加到 base上
int event_add(struct event *ev, const struct timeval *tv)
(4)循环监听事件满足
int event_base_dispatch(struct event_base *base);
(5)释放 event_base
event_base_free(base);
2、使用fifo读写(常规事件)
创建事件event
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
读操作
/*************************************************************************
> File Name: myread.c
> Author: Winter
> Created Time: 2022年02月18日 星期五 21时07分03秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <event2/event.h>
// 回调函数
void read_cb(evutil_socket_t fd, short what, void* arg) {
// 读管道
char buff[1024] = {0};
int len = read(fd, buff, sizeof(buff));
printf("read event : %s \n", what & EV_READ ? "YES" : "NO");
printf("data len = %d, buff = %s\n", len, buff);
sleep(1);
}
int main(int argc, char* argv[])
{
unlink("myfifo");
// 创建有名fifo
int res = mkfifo("myfifo", 0664);
if (res == -1) {
perror("mkfifo error\n");
exit(1);
}
// 打开fifo
int fd = open("myfifo", O_RDONLY | O_NONBLOCK); // 非阻塞只读
if (fd == -1) {
perror("open error\n");
exit(1);
}
// 创建event_base
struct event_base* base = event_base_new();
// 创建事件 EV_PERSIST是持续读
struct event* ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL);
// struct event* ev = event_new(base, fd, EV_READ, read_cb, NULL);
// 添加事件
event_add(ev, NULL);
// 事件循环
event_base_dispatch(base); // while (1) { epoll }
// 释放资源
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}
写操作
/*************************************************************************
> File Name: mywrite.c
> Author: Winter
> Created Time: 2022年02月18日 星期五 21时24分04秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <event2/event.h>
#include <fcntl.h>
// 回调函数
void write_cb(evutil_socket_t fd, short what, void* arg) {
// 写管道
char buff[1024] = {0};
static int num = 0;
sprintf(buff, "hello world - %d", num++);
write(fd, buff, strlen(buff) + 1);
sleep(1);
}
int main(int argc, char* argv[])
{
// 与myread.c配套,但是要先打开myread程序
// 打开管道
int fd = open("myfifo", O_WRONLY | O_NONBLOCK);
if (fd == -1) {
perror("open error\n");
exit(1);
}
// 创建event_base
struct event_base* base = event_base_new();
// 创建写事件 EV_PERSIST是持续写
struct event* ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);
// struct event* ev = event_new(base, fd, EV_WRITE, write_cb, NULL);
// 添加事件
event_add(ev, NULL);
// 事件循环
event_base_dispatch(base);
// 释放资源
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}
测试
这里只测试了带有EV_PERSIST参数的event_new函数。
更多推荐
所有评论(0)