libevent网络库
1、概述
libevent是一个C语言编写的、轻量级开源高性能事件通知库。作为底层网络库,已经被广泛应用(如:memcached、Vomit、Nylon、Netchat等)。主要有以下几个亮点:
- 事件驱动(event-driven)
- 高性能
- 轻量级,专注网络。
- 源码精炼,易读
- 跨平台
- 支持多种I/O多路复用技术,如epoll、poll、dev/poll、select、kqueue等。
- 支持I/O,定时器和信号等事件
- 注册事件优先级
官网地址:https://libevent.org/
2、框架介绍
1)event_base 创建与释放
// 创建event_base struct event_base* base = event_base_new() // 释放event_base_free event_base_free(struct event_base* base);
2)事件创建与释放
调用event_new()函数之后,新事件处于已初始化和非未决状态。
// 创建新事件 struct event *event_new( struct event_base *base, evutil_socket_t fd, - // 文件描述符 - int **底层是对epollin与epollout的封装** short what, event_callback_fn cb, // 事件的处理回调函数 void *arg //回调函数传参 ); // 事件的处理回调函数 typedef void (*event_callback_fn)(evutil_socket_t, short, void *); // short what #define EV_TIMEOUT 0x01 // 已淘汰(忽略) #define EV_READ 0x02 #define EV_WRITE 0x04 #define EV_SIGNAL 0x08 //libevent封装了信号相关的操作 SIGNAL #define EV_PERSIST 0x10 // 持续触发 #define EV_ET 0x20 // 边沿模式
最后需要event_free进行释放。
// 创建event_free void event_free(struct event *event);
3)event_add()函数
创建事件之后,再将其添加到event_base之前,实际上是不能对其做任何操作的。所以需要使用event_add将事件添加到event_base上去。此时状态由非未决事件->未决事件。
// event_add int event_add( struct event *ev, const struct timeval *tv );
函数调用成功返回0,失败返回-1。
4)event_base_dispatch()函数
最后,使用event_base_dispatch函数添加事件循环。
// event_base_dispatch(简化版event_base_loop()) int event_base_dispatch(struct event_base* base); //等同于没有设置标志的 event_base_loop ( ) //将一直运行,直到没有已经注册的事件了,或者调用 了event_base_loopbreak()或者 event_base_loopexit()为止
5)event_base_loop()函数
// event_base_loop() int event_base_loop(struct event_base *base, int flags); //正常退出返回0, 失败返回-1 //flages #define EVLOOP_ONCE 0x01 //事件只会被触发一次 //事件没有被触发, 阻塞等 #define EVLOOP_NONBLOCK 0x02 //非阻塞 等方式去做事件检测 //不关心事件是否被触发了 #define EVLOOP_NO_EXIT_ON_EMPTY 0x04 //没有事件的时候, 也不退出轮询检测
6)event_base_loopexit()函数
执行当前后退出。
//如果 event_base 当前正在执行激活事件的回调 ,它将在执行完当前正在处理的事件后立即退出 int event_base_loopexit( struct event_base *base, const struct timeval *tv ); //参数struct timeval *tv struct timeval { long tv_sec; long tv_usec; };
7)event_base_loopbreak()函数
立即退出循环
//让event_base 立即退出循环 int event_base_loopbreak(struct event_base *base); //返回值: 成功 0, 失败 -1
8)Demo
用例(采用fifo通信方式,不带缓冲区操作)
/************************************************************************* > File Name: read_fifi.c > Author: > Mail: > Created Time: 2021年04月19日 星期一 10时24分57秒 ************************************************************************/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<fcntl.h> #include<event2/event.h> //读取回调函数 void read_cb(evutil_socket_t fd,short what,void *arg) { //读管道 char buf[1024] = {0}; int len = read(fd,buf,sizeof(buf)); printf("data len = %d ,buf = %s\n" ,len,buf); printf("read event: %s\n",what &EV_READ ? "Yes":"No");//对what 类型对判断 } int main() { unlink("libeventfifo"); //创建有名管道 mkfifo("libeventfifo",0664); //open File int fd = open("libeventfifo",O_RDONLY | O_NONBLOCK); if(fd == -1) { perror("open error"); exit(1); } //读管道 struct event_base* base = NULL; base = event_base_new(); //创建事件 struct event* ev = NULL; ev = event_new(base,fd,EV_READ | EV_PERSIST,read_cb,NULL); // 添加事件 event_add(ev,NULL); //事件循环 event_base_dispatch(base); //释放资源 event_free(ev); event_base_free(base); close(fd); return 0 ; }
/************************************************************************* > File Name: write_fifi.c > Author: > Mail: > Created Time: 2021年04月19日 星期一 10时24分43秒 ************************************************************************/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<fcntl.h> #include<event2/event.h> //读取回调函数 void write_cb(evutil_socket_t fd,short what,void *arg) { //写管道 char buf[1024] = {0}; int len = read(fd,buf,sizeof(buf)); static int num = 999; sprintf(buf,"hello world == %d \n" ,num); write(fd,buf,strlen(buf)+1); } int main() { int fd = open("libeventfifo",O_WRONLY | O_NONBLOCK); if(fd == -1) { perror("open error"); exit(1); } struct event_base * base = NULL; base = event_base_new(); struct event* ev = NULL; 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 ; }
用gcc 分别编译文件:
gcc write_fifi.c -o write -levent gcc read_fifi.c -o read -levent
最后分别执行程序:
./read ./write