- 一、结构体
- 二、函数
- 1、event_init()
- 2、event_set()
- 3、event_add()
- 4、event_dispatch()
- 5、 event_get_supported_methods()
- 6、event_base_get_method(base)
- 7、event_base_get_features()
- 8、event_config_require_features()
- 9、event_config_new()
- 10、event_base_new 和 event_base_new_with_config
- 11、event_new()
- 12、event_dispatch 和 event_base_dispatch
- 13、event_base_free()
- 13、event_del()
- 14、evconnlistener_new_bind()
- 13、evconnlistener_free()
- 三、缓冲区相关函数
一、结构体
1、struct event_base
event_base 是一个事件集合,里面存放了多个 struct event
;
相信大家都听说过epoll吧, epoll里面有个就绪队列,就是请求已经准备好了,随时都可以拿出来进行消费, 那么event_base 就相当于是 epoll 里面的就绪队列;
event_base 是 libevent 中最核心的一个结构体,它代表了一个事件循环基础。它负责管理事件的注册、触发和分发等操作。
struct event_base 的定义如下:
struct event_base {
/* 事件通知机制的实现细节 */
const struct eventop *evsel;
void *evbase;
/* 事件队列 */
struct event_list **activequeues;
int nactivequeues;
struct event_list eventqueue;
struct event_list watcherqueue;
/* 时间管理 */
struct timeval tv_cache;
int tv_cache_set;
/* 其他配置 */
int event_count;
int event_count_active;
int event_count_dirty;
int running_loop;
enum event_base_state term_stamp;
enum event_base_config_flag flags;
void *user_data;
struct event_debug_logging_data *debug_logging;
};
下面是各个成员的详细说明:
- evsel: 这个成员指向一个 struct eventop 对象,它代表了具体的事件通知机制的实现,比如epoll、kqueue、select等。
- evbase: 这个成员指向具体事件通知机制的私有数据。
- activequeues: 这个成员是一个数组,用于存储各个优先级的活动事件队列。
- nactivequeues: 这个成员记录了 activequeues 数组中有效元素的数量。
- eventqueue: 这个成员是一个链表,用于存储已注册但尚未激活的事件。
- watcherqueue: 这个成员是一个链表,用于存储系统时钟变化的事件观察者。
- tv_cache: 这个成员缓存了最近一次调用 event_base_get_timeval 时返回的时间值。
- tv_cache_set: 这个成员标记了 tv_cache 是否已经被设置。
- event_count: 这个成员记录了已注册的事件数量。
- event_count_active: 这个成员记录了当前活动的事件数量。
- event_count_dirty: 这个成员记录了需要重新排序的事件数量。
- running_loop: 这个成员标记了当前是否正在运行事件循环。
- term_stamp: 这个成员记录了事件基础的终止状态。
- flags: 这个成员存储了事件基础的配置选项。
- user_data: 这个成员可用于存储自定义的数据。
- debug_logging: 这个成员用于记录调试信息。
event_base 对象的主要功能包括:
- 提供事件注册和触发机制。
- 管理事件队列,包括活动队列和待处理队列。
- 提供定时器功能。
- 处理信号。
- 提供跨平台的事件通知机制抽象。
2、 struct event
刚刚说了 event_base 集合里面存放了多个 struct event
,
那这里每个struct event
都是一个事件或者是一个信号,也可以说 每个 struct event
都是一个个的请求;
3、struct event_config
event_config 是 libevent 中用于配置 event_base 对象的结构体。它允许您在创建 event_base 对象时指定一些特定的选项和行为。
下面是各个成员的详细说明:
- avoid_method: 这个成员是一个函数指针,用于指定不希望使用的事件通知机制。例如,您可以通过设置 avoid_method(“epoll”) 来禁用 epoll 事件通知机制。
- feature_enabled: 这个成员是一个函数指针,用于检查指定的事件通知机制特性是否被启用。您可以使用它来确保选择的事件通知机制具有您需要的特性。
- flags: 这个成员是一个枚举类型 event_base_config_flag,用于指定 event_base 对象的配置选项。可选的配置选项有:
- EVENT_BASE_FLAG_NOLOCK: 禁用事件基础的锁机制。
- EVENT_BASE_FLAG_IGNORE_ENV: 忽略环境变量,不从中读取配置信息。
- EVENT_BASE_FLAG_STARTUP_IOCP: 在Windows系统上使用IOCP作为事件通知机制。
- num_cpus_hint: 这个成员用于指定系统 CPU 的数量,libevent 可以利用这个信息进行一些优化。
- userdata: 这个成员可用于存储自定义的数据,在 event_config_new_from_env 和 event_config_free 函数中会用到。
二、函数
1、event_init()
初始化一个事件集合,返回值为 struct event_base*
,以下是event_init函数的一般语法和参数解释:
struct event_base *event_init(void);
返回值:
- 返回一个指向event_base结构体的指针,表示初始化成功的事件处理器基础结构。
event_init函数的作用是初始化一个事件处理器的基础结构,为事件循环做好准备。在初始化完成后,可以将事件添加到事件处理器中,并启动事件循环。
如果不需要用到 event_base ,可以不返回,因为调用 event_init 函数后会自动将 event_base 赋值给全局变量;
2、event_set()
初始化事件,将事件(struct event)和 文件描述符(fd)进行绑定,
以下是event_set函数的一般语法和参数解释:
int event_set(struct event *ev, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg);
参数解释:
- ev: 指向event结构体的指针,表示需要设置的事件。
- fd: 一个表示文件描述符的evutil_socket_t类型参数,表示事件要关联的文件描述符。
- events: 一个short类型的参数,表示事件类型,事件类型由以下宏定义表示:
- EV_TIMEOUT:超时事件,即在指定的时间间隔之后触发。
- EV_READ:读事件,当文件描述符可读时触发。
- EV_WRITE:写事件,当文件描述符可写时触发。
- EV_SIGNAL:信号事件,当指定的信号发生时触发。
- EV_PERSIST:持久事件,即事件在触发后仍然保持激活状态,直到显式删除。
- EV_ET:边缘触发事件,仅在文件描述符状态发生变化时触发一次。
- callback: 一个函数指针,表示事件发生时要调用的回调函数。
- arg: 一个void类型的参数,传递给回调函数作为参数。
event_set函数的作用是将上述参数设置到event结构体中,以便后续添加到事件循环中。一旦设置完成,事件循环会监听与fd相关的指定事件,当事件发生时调用回调函数进行处理。
3、event_add()
将事件添加到集合中,使事件得以监听和触发。以下是event_add函数的一般语法和参数解释:
int event_add(struct event *ev, const struct timeval *timeout);
参数解释:
- ev: 指向event结构体的指针,表示需要添加到事件循环中的事件。
- timeout: 指向struct timeval结构体的指针,表示事件的超时时间。如果设置为NULL,则事件会一直持续监听,直到事件被移除。
event_add函数的作用是将事件ev添加到事件循环中,并开始监听事件。当事件发生时,事件循环将会调用之前通过event_set函数设置的回调函数进行处理。timeout参数可以用来设置事件的超时时间,在超时时间内如果事件未发生,也会触发回调函数。
4、event_dispatch()
event_dispatch函数用于启动事件循环,
将事件添加进事件集合后,就可以调用 event_dispatch 开始监听注册的事件,并且在事件发生时执行相应的回调函数。以下是event_dispatch函数的一般语法和简要说明:
int event_dispatch(void);
event_dispatch函数无需参数,它的作用是启动事件循环,使事件处理器开始监听注册的事件。一旦事件循环启动,它会不断地监听注册的事件,当事件发生时,调用相应的回调函数进行处理。事件循环会持续运行,直到所有事件处理完成或者手动停止事件循环。也就是说,event_dispatch 内部其实是个死循环,会一直监听事件,如果没有事件可监听了,则会退出循环;
5、 event_get_supported_methods()
获取当前支持的方法有哪些,该函数返回一个数组,用法
const char **methods = event_get_supported_methods();
for (int i = 0; methods[i] != NULL; ++i) {
printf("支持的方式:%s\n",methods[i]);
methods ++;
}
打印结果
支持的方式:epoll
支持的方式:select
6、event_base_get_method(base)
获取当前使用的多路复用技术,用法
const char *method = event_base_get_method(base);
printf("Using event method: %s\n", method);
打印结果
Using event method: epoll
7、event_base_get_features()
event_base_get_features 函数是 libevent 库中用于获取 event_base 对象所支持的特性的函数,定义如下
int event_base_get_features(const struct event_base *base){
if (base == NULL)
return (0);
return (base->evsel->features);
}
该函数接受一个 event_base 对象作为参数,并返回该 event_base 对象所支持的特性,
特性通过一组宏定义来表示,这些宏定义定义在 event2/event.h 头文件中,包括:
- EV_FEATURE_ET:表示该 event_base 支持边缘触发模式。
- EV_FEATURE_O1:表示该 event_base 支持 O(1) 时间复杂度的事件添加和删除操作。
- EV_FEATURE_FDS:表示该 event_base 支持监听文件描述符。
- EV_FEATURE_EARLY_CLOSE:表示该 event_base 支持在事件处理函数中关闭文件描述符。
若要设置事件处理特性,请看 event_config_require_features 函数
8、event_config_require_features()
该函数的作用。
event_config_require_features 函数是设置 event_config 对象的 require_features 成员变量,指定在创建 event_base 对象时所需的事件处理特性。它的定义如下:
void event_config_require_features(struct event_config *cfg, int features){
cfg->require_features |= features;
}
该函数接受两个参数:
- cfg: 一个指向 event_config 对象的指针。
- features: 一个表示所需事件处理特性的位掩码。
features 参数可以是以下几个值的按位或运算:
- EV_FEATURE_ET: 表示需要支持边缘触发模式。
- EV_FEATURE_O1: 表示需要支持 O(1) 时间复杂度的事件添加和删除操作。
- EV_FEATURE_FDS: 表示需要支持监听文件描述符。
- EV_FEATURE_EARLY_CLOSE: 表示需要支持在事件处理函数中关闭文件描述符。
若要获取事件处理特性,请看 event_base_get_features 函数
9、event_config_new()
event_config_new() 函数是 libevent 库中用于创建一个新的 event_config 对象的函数。并使用默认的配置,它的定义如下:
struct event_config * event_config_new(void){
struct event_config *cfg = mm_calloc(1, sizeof(struct event_config));
if (cfg == NULL)
return NULL;
/* 初始化 event_config 对象的各个成员变量 */
cfg->n_backends = 0;
cfg->avoid_method = NULL;
cfg->require_features = 0;
cfg->disable_features = 0;
cfg->num_cpus = 0;
cfg->max_dispatch_interval = 0;
cfg->max_exact_secs = 0;
cfg->max_dispatch_callbacks = 0;
return cfg;
}
下面是 event_config_new() 函数的主要功能:
- 使用 mm_calloc() 函数分配一块内存来存储 event_config 对象。
- 初始化 event_config 对象的各个成员变量。
event_config 对象是用于配置 event_base 对象的一种机制。它可以用来指定事件处理机制的特性、CPU 核心数、最大事件分发间隔等参数。这些参数将在创建 event_base 对象时被使用。
需要注意的是,event_config 是在 event_config_new 函数内动态分配了内存空间的,所以使用完成后一定要用 event_config_free 函数进行释放
// 用完之后一定要释放 event_config
event_config_free(cfg);
10、event_base_new 和 event_base_new_with_config
event_base_new_with_config 和 event_base_new 函数都是 libevent 库中用于创建 event_base 对象的函数,它们的主要区别在于是否使用 event_config 对象进行配置;
10.1、event_base_new
struct event_base * vent_base_new(void) {
return event_base_new_with_config(NULL);
}
该函数直接创建一个新的 event_base 对象,不使用任何 event_config 对象进行配置。它会使用 libevent 库默认的配置参数来创建 event_base 对象。
10.2、event_base_new_with_config
struct event_base * vent_base_new_with_config(const struct event_config *cfg){
struct event_base *base;
/* 根据 event_config 对象的配置创建 event_base 对象 */
base = event_base_new_with_method(cfg->avoid_method,
cfg->require_features,
cfg->disable_features,
cfg->num_cpus,
cfg->max_dispatch_interval,
cfg->max_exact_secs,
cfg->max_dispatch_callbacks);
return base;
}
该函数接受一个 event_config 对象作为参数,根据该对象的配置创建一个新的 event_base 对象。它会使用 event_config 对象中设置的各种参数,如事件处理机制、CPU 核心数、最大事件分发间隔等,来创建 event_base 对象。
11、event_new()
该函数的作用是创建一个新的 event 对象,并将其与指定的 event_base 对象、文件描述符、事件类型和回调函数关联起来。它内部调用了 event_assign 函数来完成实际的初始化工作。它的定义如下:
struct event * event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn cb, void *arg){
return event_assign(NULL, base, fd, events, cb, arg);
}
该函数接受以下参数:
- base: 一个指向 event_base 对象的指针,用于指定事件处理机制。
- fd: 要监听的文件描述符。
- events: 要监听的事件类型,可以是以下值的按位或:
- EV_READ: 监听读事件。
- EV_WRITE: 监听写事件。
- EV_SIGNAL: 监听信号事件。
- EV_PERSIST: 设置事件为持久型,即事件触发后不会自动从事件队列中移除。
- cb: 事件触发时要调用的回调函数,该函数需要满足以下原型:
void callback(evutil_socket_t, short, void *);
- arg: 要传递给回调函数的参数。
通过 event_new 创建事件对象后,需要使用 event_set 来配置事件对象的属性,才能使其生效
12、event_dispatch 和 event_base_dispatch
event_dispatch 函数是一个更加简单和便捷的函数,但是它限制了您对事件循环行为的控制。而 event_base_dispatch 函数则提供了更多的灵活性,您可以自定义事件循环的行为,但同时也需要更多的代码来管理 event_base 对象。
event_dispatch 和 event_base_dispatch 都是 libevent 中用于启动事件循环的函数,但它们之间有一些区别
- event_dispatch函数内部调用了 event_base_get_default() 函数来获取默认的 event_base 对象,然后再调用 event_base_dispatch 函数启动事件循环。它是一个便捷函数,用于在没有自定义 event_base 对象的情况下启动事件循环
- event_base_dispatch 函数要求您显式地传入一个 event_base 对象,而不是使用默认的 event_base 对象。这使得您可以更好地控制事件循环的行为,例如可以使用不同的事件循环标志来更改事件循环的行为
event_dispatch 函数的定义如下:
12.1、event_dispatch
event_dispatch 函数的定义如下:
int event_dispatch(void) {
return event_base_dispatch(event_base_get_default());
}
这个函数内部调用了 event_base_get_default() 函数来获取默认的 event_base 对象,然后再调用 event_base_dispatch 函数启动事件循环。它是一个便捷函数,用于在没有自定义 event_base 对象的情况下启动事件循环。
12.2、event_base_dispatch
event_base_dispatch 函数的定义如下:
int event_base_dispatch(struct event_base *event_base)
{
return event_base_loop(event_base, EVLOOP_DEFAULT);
}
这个函数内部调用了 event_base_loop 函数来启动事件循环,并传递了 EVLOOP_DEFAULT 作为事件循环的行为标志。
与 event_dispatch 函数不同的是, event_base_dispatch 函数要求您显式地传入一个 event_base 对象,而不是使用默认的 event_base 对象。这使得您可以更好地控制事件循环的行为,例如可以使用不同的事件循环标志来更改事件循环的行为。
13、event_base_free()
event_base_free 函数是 libevent 中用于释放 event_base 对象的函数。它的定义如下:
void event_base_free(struct event_base *event_base){
event_base_free_nofinalize(event_base, 0);
}
该函数内部调用了 event_base_free_nofinalize 函数来完成实际的释放操作。
event_base_free_nofinalize 函数的定义如下:
void event_base_free_nofinalize(struct event_base *event_base, int flags) {
if (!event_base)
return;
/* 停止事件循环 */
event_base_loopbreak(event_base);
/* 释放与 event_base 关联的资源 */
event_base_free_everything(event_base);
/* 释放 event_base 对象本身 */
mm_free(event_base);
}
该函数主要完成以下几个步骤:
- 停止事件循环: 首先调用 event_base_loopbreak 函数来停止事件循环,确保所有事件处理完毕。
- 释放资源: 接下来调用 event_base_free_everything 函数来释放与 event_base 对象关联的各种资源,包括事件、信号、定时器等。
- 释放 event_base 对象: 最后使用 mm_free 函数释放 event_base 对象本身。
- 需要注意的是,在释放 event_base 对象之前,需要先将所有与之关联的事件、信号等资源全部释放掉,否则可能会引发内存泄漏或其他问题。
13、event_del()
event_del 函数的作用是将指定的事件对象从事件循环中移除,停止监听相应的事件类型,并且不再触发对应的回调函数。调用 event_del 后,该事件对象的生命周期并没有结束,可以继续使用 event_add 将其添加回事件循环中,或者使用 event_free 来释放资源。
函数签名如下:
int event_del(struct event *ev);
参数 ev 是指向要删除的事件对象的指针。
调用 event_del 函数后,如果成功将事件对象从事件循环中删除,则会返回 0,否则返回 -1。
总之,event_del 函数用于将一个已存在的事件对象从事件循环中删除,停止监听相应的事件类型,是对 event_add 的一个逆操作。
14、evconnlistener_new_bind()
evconnlistener_new_bind函数用于创建一个网络监听器,用于接受传入的连接请求。通俗地讲,这个函数其实就是封装了 socket、bind、listener、accept 这四个函数;
它接受event_base结构作为参数,表示监听器将注册到哪个事件循环中。
你需要指定回调函数来处理新连接事件,以及其他参数如监听地址、端口等。
创建的监听器对象会自动将对应的事件添加到事件循环中,无需调用event_add。
监听器对象需要在使用完毕后通过调用evconnlistener_free函数进行释放。
函数签名如下:
struct evconnlistener *evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, int socklen);
参数解释:
- base:指向事件循环(event_base)的指针。
- cb:一个回调函数,用于处理新连接。
- ptr:用户自定义数据,将会传递给回调函数。
- flags:标志位,用于指定监听器的选项。有以下可选值:
- LEV_OPT_CLOSE_ON_FREE:在释放listener时关闭底层套接字。
- LEV_OPT_REUSEABLE:设置底层套接字为可重用。
- LEV_OPT_CLOSE_ON_EXEC:关闭底层套接字的执行标志。
- LEV_OPT_THREADSAFE:使底层套接字的操作线程安全。
- LEV_OPT_DEFERRED_ACCEPT:推迟接受连接,直到调用event_accept函数。
- LEV_OPT_REUSEABLE_PORT:设置端口重用标志。
- backlog:套接字监听的连接队列的最大长度。这个参数其实就是给listen函数的第2个参数传参用的
- sa:指向要绑定的地址的 sockaddr 结构体指针。 这个参数其实就是给 bind 函数的第2个参数传参用的
- socklen:sa 的长度。使用 sizeof 计算即可,如 sizeof(sa), 这个参数其实就是给 bind 函数的第3个参数传参用的
evconnlistener_cb 回调函数结构如下
void evconnlistener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx);
参数解释:
- listener:指向触发事件的监听器对象的指针。
- fd:新连接的套接字描述符。
- address:新连接的地址信息。
- socklen:address 结构的长度。
- ctx:传递给监听器的上下文数据,通常是一个指向用户自定义数据的指针。
在编写 evconnlistener_cb 类型的回调函数时,你可以根据具体的业务逻辑处理需求来编写逻辑,例如接受新连接、处理数据、发送响应等操作。
13、evconnlistener_free()
evconnlistener_free 函数用于释放和销毁一个套接字监听器对象。
具体来说,evconnlistener_free 函数的作用是释放指定的套接字监听器对象,并清理其相关资源,包括关闭监听套接字、停止监听等。
函数签名如下:
void evconnlistener_free(struct evconnlistener *lev);
参数 lev 是指向要释放的套接字监听器对象的指针。
调用 evconnlistener_free 函数可以释放指定的套接字监听器对象,释放相关资源,包括关闭监听套接字,并且停止监听。在不需要监听新连接事件时,可以调用该函数来释放监听器对象,以避免资源泄漏。
总之,evconnlistener_free 函数用于释放和销毁一个套接字监听器对象,清理其相关资源,包括关闭监听套接字、停止监听等。
三、缓冲区相关函数
14、bufferevent_read()
bufferevent_read函数是libevent库中用于从一个bufferevent中读取数据的函数。其原型为:
int bufferevent_read(struct bufferevent *bev, void *data, size_t size);
参数解释:
- bev:指向要读取数据的bufferevent的指针。
- data:要存储读取数据的缓冲区的指针。
- size:要读取数据的大小。
这个函数会尝试从bufferevent bev 中读取最多size个字节的数据,然后将数据存储到data指向的缓冲区中。如果成功读取了数据,返回值为实际读取的字节数;如果读取失败,返回-1并设置错误信息(可以通过errno或bufferevent_get_op_errror函数获取)。
需要注意的是,bufferevent_read函数是一个非阻塞的函数,如果缓冲区中没有足够的数据可读,则会返回0字节并不会阻塞。因此,在调用该函数前需要确保bufferevent处于可读状态,可以通过注册读事件的回调函数来实现数据的读取。
15、bufferevent_write()
bufferevent_write函数是libevent库中用于向一个bufferevent中写入数据的函数。其原型为:
int bufferevent_write(struct bufferevent *bev, const void *data, size_t size);
参数解释:
- bev:指向要写入数据的bufferevent的指针。
- data:要写入的数据的缓冲区的指针。
- size:要写入的数据的大小。
这个函数会尝试向bufferevent bev 中写入最多size个字节的数据,数据来自于data指向的缓冲区。如果成功写入了数据,返回值为实际写入的字节数;如果写入失败,返回-1并设置错误信息(可以通过errno或bufferevent_get_op_error函数获取)。
需要注意的是,bufferevent_write函数是一个非阻塞的函数,如果写入时缓冲区已满,则会返回0字节并不会阻塞。因此,在调用该函数前需要确保bufferevent处于可写状态,可以通过注册写事件的回调函数来实现数据的写入。
16、bufferevent_get_input()
bufferevent_get_input函数是libevent库中用于获取bufferevent中输入缓冲区的函数。其原型为:
struct evbuffer *bufferevent_get_input(struct bufferevent *bev);
参数解释:
- bev:指向要获取输入缓冲区的bufferevent的指针。
该函数返回一个指向输入缓冲区的struct evbuffer结构体的指针。evbuffer结构体代表一个libevent中的缓冲区,在这里主要用于存储bufferevent接收到的数据。
通过调用bufferevent_get_input函数,可以获取bufferevent中已经接收但还未处理的数据。通常情况下,要读取数据或者进行其他操作,可以直接操作这个返回的evbuffer对象。
需要注意的是,这个函数只是返回指向输入缓冲区的指针,不会对缓冲区中的数据进行任何操作。需要在函数返回后自行处理缓冲区中的数据。
17、bufferevent_get_output()
bufferevent_get_output 函数是libevent库中用于获取bufferevent中输出缓冲区的函数。其原型为:
struct evbuffer *bufferevent_get_output(struct bufferevent *bev);
参数解释:
- bev:指向要获取输出缓冲区的bufferevent的指针。
该函数返回一个指向输出缓冲区的struct evbuffer结构体的指针。evbuffer结构体代表一个libevent中的缓冲区,在这里主要用于存储bufferevent将要发送的数据。
通过调用bufferevent_get_output函数,可以获取bufferevent中待发送的数据。通常情况下,需要将数据写入到输出缓冲区中,然后通过bufferevent将数据发送出去。
需要注意的是,这个函数只是返回指向输出缓冲区的指针,不会对缓冲区中的数据进行任何操作。需要在函数返回后自行处理缓冲区中的数据。
18、evbuffer_remov()
evbuffer_remove函数是libevent库中用于从evbuffer缓冲区中移除数据的函数。其原型为:
int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
参数解释:
- buf:指向要从中移除数据的evbuffer缓冲区的指针。
- data:指向存放移除的数据的缓冲区的指针。
- datlen:要移除的数据的大小。
这个函数会尝试从evbuffer缓冲区buf中移除最多datlen个字节的数据,并将移除的数据存放在data指向的缓冲区中。如果成功移除了数据,返回值为实际移除的字节数;如果移除失败,返回-1并设置错误信息(可以通过errno或其他适当的错误处理函数获取)。
需要注意的是,evbuffer_remove函数会从evbuffer中移除数据并且将其返回给调用者。在移除数据后,evbuffer中的数据将会减少相应的字节数。
19、evbuffer_add()
evbuffer_add 函数是libevent库中用于向evbuffer缓冲区中添加数据的函数。其原型为:
int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
参数解释:
- buf:指向要添加数据的evbuffer缓冲区的指针。
- data:指向要添加到缓冲区的数据的指针。
- datlen:要添加的数据的大小。
这个函数会向evbuffer缓冲区buf中添加datlen字节大小的数据,数据内容为data指向的内存。如果成功添加数据,返回值为0;如果添加失败,返回-1并设置错误信息(可以通过errno或其他适当的错误处理函数获取)。
需要注意的是,evbuffer_add函数会向evbuffer中添加数据,使缓冲区中的数据增加相应的字节数。添加数据后,可以通过bufferevent将数据发送出去,或者通过其他方式处理。
20、evbuffer_get_length()
evbuffer_get_length函数是libevent库中用于获取evbuffer缓冲区中当前有效数据长度的函数。其原型为:
size_t evbuffer_get_length(const struct evbuffer *buf);
参数解释:
- buf:指向要获取长度的evbuffer缓冲区的指针。
这个函数会返回evbuffer缓冲区buf中当前有效数据的总长度。也就是说,返回值表示缓冲区中所有未读取或未发送的数据的总大小。经过测试,若客户端发送过来的数据太大,则evbuffer_get_length函数每次最大值只能获取到 4096
通常情况下,通过调用evbuffer_get_length函数可以获取evbuffer缓冲区中当前的缓冲数据长度,以便进行后续处理,比如决定是否继续接收数据或发送数据,或者对数据进行其他处理。
需要注意的是,这个函数只是返回当前有效数据的长度,并不会修改缓冲区中的数据。
21、bufferevent_setcb()
bufferevent_setcb函数是libevent库中用于设置bufferevent事件回调函数的函数。其原型为:
void bufferevent_setcb(struct bufferevent *bev, bufferevent_data_cb readcb, bufferevent_data_cb writecb, bufferevent_event_cb eventcb, void *cbarg);
参数解释:
- bev:指向要设置回调函数的bufferevent结构的指针。
- readcb:读事件的回调函数,当bufferevent从其输入缓冲区中读取数据时调用。
- writecb:写事件的回调函数,写成功后的回调。
- eventcb:事件(如错误、连接关闭等)发生时的回调函数,如:异常退出、按下ctrl+c时就会触发此回调
- cbarg:可选参数,作为回调函数的参数传递。
通过调用bufferevent_setcb函数,可以为指定的bufferevent设置相应的事件回调函数。当注册的事件发生时,对应的回调函数将会被调用。在回调函数中,可以处理相应的事件,比如读取数据、写入数据、处理错误等。
需要注意的是,一旦设置了回调函数,当相应的事件发生时,libevent将会自动调用相应的回调函数。
21.1、bufferevent_event_cb 回调函数详解
bufferevent_event_cb 是 Libevent 库中 struct bufferevent 的一个回调函数类型,用于处理 bufferevent 对象的事件。这个回调函数在 bufferevent 对象发生状态变化时被调用。
函数原型如下:
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx);
其中:
- struct bufferevent *bev: 表示发生事件的 bufferevent 对象。
- short events: 表示发生的事件类型,可以是以下几种:
- BEV_EVENT_READING: 表示 bufferevent 对象可读。
- BEV_EVENT_WRITING: 表示 bufferevent 对象可写。
- BEV_EVENT_EOF: 表示对方已经关闭连接。
- BEV_EVENT_ERROR: 表示发生错误。
- BEV_EVENT_TIMEOUT: 表示读写超时。
- BEV_EVENT_CONNECTED: 表示连接已经建立。
- void *ctx: 表示用户自定义的上下文数据,在注册回调函数时传递。
当 bufferevent 对象发生事件时,Libevent 库会调用这个回调函数,并传入相应的事件标志和用户自定义的上下文数据。
22、bufferevent_enable() 和 bufferevent_disable()
22.1、bufferevent_enable()
bufferevent_enable函数是libevent库中用于启用bufferevent事件的函数。其原型为:
void bufferevent_enable(struct bufferevent *bev, short event);
参数解释:
- bev:指向要启用事件的bufferevent结构的指针。
- event:要启用的事件类型,可以是以下常量的组合:
- EV_READ:允许读取数据,即使没有数据可供读取。
- EV_WRITE:允许写入数据,即使输出缓冲区未满。
通过调用bufferevent_enable函数,可以根据需要启用bufferevent结构中的特定事件。启用事件后,bufferevent将会监视相应的事件,并在事件发生时触发相应的回调函数(如果已经设置了回调函数)。
需要注意的是,当事件被启用后,libevent将会开始监视并处理相应的事件,用户需要确保事件回调函数已经设置好,以便处理事件。
22.2、bufferevent_disable()
bufferevent_disable函数是libevent中用于禁用bufferevent结构中特定事件的函数。其原型为:
void bufferevent_disable(struct bufferevent *bev, short event);
参数解释:
- bev:指向要禁用事件的bufferevent结构的指针。
- event:要禁用的事件类型,可以是以下常量的组合:
- EV_READ:允许读取数据,即使没有数据可供读取。
- EV_WRITE:允许写入数据,即使输出缓冲区未满。
通过调用bufferevent_disable函数,可以根据需要禁用bufferevent结构中的特定事件。禁用事件后,bufferevent将不再监视相应的事件,也不会触发相应的回调函数。
需要注意的是,当事件被禁用后,对应的事件将不再被处理,直到再次启用该事件。如果之前已经设置了事件回调函数,需要谨慎地禁用事件,以免影响程序逻辑。
23、bufferevent_socket_new()
bufferevent_socket_new函数是libevent中一个用于创建套接字相关的bufferevent实例的函数。其原型为:
struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options);
参数解释:
- base:指向要将bufferevent注册到的事件基础结构的指针。
- fd:一个套接字文件描述符,用于与bufferevent通信。
- options:选项参数,用于指定bufferevent的行为。常见的选项包括:
- BEV_OPT_CLOSE_ON_FREE:释放bufferevent时关闭底层套接字。
- BEV_OPT_THREADSAFE:允许在多线程环境中使用bufferevent。
bufferevent_socket_new函数创建一个新的用于处理套接字的bufferevent实例,并将其绑定到指定的事件基础结构。这个函数通常用于在网络编程中创建与远程主机通信的bufferevent实例。
返回的struct bufferevent指针指向新创建的bufferevent实例,您可以使用它来对bufferevent进行操作,比如设置回调函数、启用事件等。
需要注意的是,在使用完bufferevent后,您需要调用bufferevent_free函数来释放由bufferevent_socket_new创建的bufferevent实例,以避免内存泄漏。