目录
创建/释放基于套接字的bufferevent bufferevent_socket_new
在bufferevent上启动连接服务器函数 bufferevent_socket_connect
bufferevent读写缓冲区回调操作 bufferevent_setcb
操作bufferevent中的数据 bufferevent_write bufferevent_read
1. Libevent介绍
Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:
- > - 事件驱动( event-driven),高性能;
- > - 轻量级,专注于网络;
- > - 源代码相当精炼、易读;
- > - 跨平台,支持 Windows、 Linux、 BSD(是Unix的衍生系统) 和 Mac OS;
- > - 支持多种 I/O 多路复用技术, epoll、 poll、 select 和 kqueue 等;
- > - 支持 I/O,定时器和信号等事件;
- > - 支持注册事件优先级。
1.1 安装Libevent
- 下载地址: http://libevent.org/
- 安装步骤 -> 源码安装的方式(终端打开下载目录)
1. 可执行程序: configure ./configure // 检测安装环境, 并且生成一个makefile文件 2. 根据makefile中的构建规则编译源代码 make 3. 安装 sudo make install //将得到可执行程序/动态库/静态库/头文件拷贝到系统目录
- 动态库找不到问题解决:
1. 通过find命令查找对应的库的位置
find 搜索目录 -name "libevent.so"
得到结果: /usr/local/lib/libevent.so
2. 通过vi 打开/etc/ld.so.conf文件
sudo /etc/ld.so.conf
将/usr/local/lib/放到文件的最后一行, 保存
3. 执行命令: sudo ldconfig
编译要加上动态库event hello.c
gcc hello.c -o hello -levent
2. 事件处理框架 - event_base
使用 libevent函数之前需要分配一个或者多个 event_base 结构体。每个event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。每个 event_base 都有一种用于检测哪种事件已经就绪的 “方法”。
2.1 event_base API函数
// 头文件
#include <event2/event.h>
// 操作函数
struct event_base * event_base_new(void); //创建事件处理框架
void event_base_free(struct event_base * base); //释放事件处理框架
// 检查event_base的后端方法
const char** event_get_supported_methods(void);
const char *event_base_get_method(const struct event_base *base);
event_base和fork(进程)关系:
- 子进程创建成功之后, 父进程可以继续使用event_base
- 子进程中需要继续使用event_base需要用下面函数,重新初始化
int event_reinit(struct event_base* base);
例子:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <event2/event.h>
int main()
{
// 1. 创建事件处理框架
struct event_base* base = event_base_new();
// 打印支持的IO转接函数
const char** method = event_get_supported_methods();
for(int i=0; method[i] != NULL; ++i)
{
printf("%s\n", method[i]);
}
printf("current method: %s\n", event_base_get_method(base));
// 创建子进程
pid_t pid = fork();
if(pid == 0)
{
// 子进程中event_base也会被复制,在使用这个base时候要重新初始化
event_reinit(base);
}
// 2. 释放资源
event_base_free(base);
return 0;
}
3. 事件循环
event_base不停的检测委托的检测是实际是不是发生了, 如果发生了, event_base会调用对应的回调函数, 这个回调函数的用户委托检测事件的时候给的.
3.1 设置事件循环
如果委托了event_base检测某些事件, 不停的进行循环检测
结束检测时间: 所有要检测的事件都被触发, 并且处理完毕。
// 头文件
#include <event2/event.h>
// 操作函数
#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
int event_base_loop(struct event_base *base, int flags);
参数:
- base: 通过 event_base_new(void)得到的
- flags:
- EVLOOP_ONCE: 一直检测某个事件, 当事件被触发了, 停止事件循环
- EVLOOP_NONBLOCK: 非阻塞的方式检测, 当事件被触发了, 停止事件循环
- EVLOOP_NO_EXIT_ON_EMPTY: 一直进行事件检测, 如果没有要检测的事件, 不退出
int event_base_dispatch(struct event_base* base); // 一般使用这个函数
参数:
- base: 通过 event_base_new(void)得到的
3.2 终止事件循环
// 头文件
#include <event2/event.h>
struct timeval {
long tv_sec;
long tv_usec; // 微秒
};
// 在 tv 时长之后退出循环, 如果这个参数为空NULL, 直接退出事件循环
// 事件循环: 检测对应的事件是否被触发了
// 如果事件处理函数正在被执行, 执行完毕之后才终止
int event_base_loopexit(struct event_base * base, const struct timeval * tv);
// 马上终止
int event_base_loopbreak(struct event_base * base);
4. 事件
4.1 事件基本操作
-
事件的创建 event_new
#include <event2/event.h>
//要检测事件 what:
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10 // 修饰某个事件是持续触发的
#define EV_ET 0x20 // 边沿模式
//回调函数格式:
typedef void (*event_callback_fn)(evutil_socket_t,short,void *);
参数:
- 第一个参数: event_new的第二个参数
- 第二个参数: 实际触发的事件
- 第三个参数: event_new的最后一个参数
// 创建事件
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: 文件描述符, 检测这个fd对应的事件
- what: 监测fd的什么事件
- cb: 回调函数, 当前检测的事件被触发, 这个函数被调用
- arg: 给回调函数传参
-
事件的释放
#include <