libevent 函数和结构体介绍

发布时间:2024-05-23 22:04:21 作者:yexindonglai@163.com 阅读(89)

一、结构体

1、struct event_base

event_base 是一个事件集合,里面存放了多个 struct event
相信大家都听说过epoll吧, epoll里面有个就绪队列,就是请求已经准备好了,随时都可以拿出来进行消费, 那么event_base 就相当于是 epoll 里面的就绪队列;

event_base 是 libevent 中最核心的一个结构体,它代表了一个事件循环基础。它负责管理事件的注册、触发和分发等操作。

struct event_base 的定义如下:

  1. struct event_base {
  2. /* 事件通知机制的实现细节 */
  3. const struct eventop *evsel;
  4. void *evbase;
  5. /* 事件队列 */
  6. struct event_list **activequeues;
  7. int nactivequeues;
  8. struct event_list eventqueue;
  9. struct event_list watcherqueue;
  10. /* 时间管理 */
  11. struct timeval tv_cache;
  12. int tv_cache_set;
  13. /* 其他配置 */
  14. int event_count;
  15. int event_count_active;
  16. int event_count_dirty;
  17. int running_loop;
  18. enum event_base_state term_stamp;
  19. enum event_base_config_flag flags;
  20. void *user_data;
  21. struct event_debug_logging_data *debug_logging;
  22. };

下面是各个成员的详细说明:

  1. evsel: 这个成员指向一个 struct eventop 对象,它代表了具体的事件通知机制的实现,比如epoll、kqueue、select等。
  2. evbase: 这个成员指向具体事件通知机制的私有数据。
  3. activequeues: 这个成员是一个数组,用于存储各个优先级的活动事件队列。
  4. nactivequeues: 这个成员记录了 activequeues 数组中有效元素的数量。
  5. eventqueue: 这个成员是一个链表,用于存储已注册但尚未激活的事件。
  6. watcherqueue: 这个成员是一个链表,用于存储系统时钟变化的事件观察者。
  7. tv_cache: 这个成员缓存了最近一次调用 event_base_get_timeval 时返回的时间值。
  8. tv_cache_set: 这个成员标记了 tv_cache 是否已经被设置。
  9. event_count: 这个成员记录了已注册的事件数量。
  10. event_count_active: 这个成员记录了当前活动的事件数量。
  11. event_count_dirty: 这个成员记录了需要重新排序的事件数量。
  12. running_loop: 这个成员标记了当前是否正在运行事件循环。
  13. term_stamp: 这个成员记录了事件基础的终止状态。
  14. flags: 这个成员存储了事件基础的配置选项。
  15. user_data: 这个成员可用于存储自定义的数据。
  16. debug_logging: 这个成员用于记录调试信息。

event_base 对象的主要功能包括:

  1. 提供事件注册和触发机制。
  2. 管理事件队列,包括活动队列和待处理队列。
  3. 提供定时器功能。
  4. 处理信号。
  5. 提供跨平台的事件通知机制抽象。

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函数的一般语法和参数解释:

  1. struct event_base *event_init(void);

返回值:

  • 返回一个指向event_base结构体的指针,表示初始化成功的事件处理器基础结构。

event_init函数的作用是初始化一个事件处理器的基础结构,为事件循环做好准备。在初始化完成后,可以将事件添加到事件处理器中,并启动事件循环。

如果不需要用到 event_base ,可以不返回,因为调用 event_init 函数后会自动将 event_base 赋值给全局变量;

2、event_set()

初始化事件,将事件(struct event)和 文件描述符(fd)进行绑定,

以下是event_set函数的一般语法和参数解释:

  1. 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函数的一般语法和参数解释:

  1. 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函数的一般语法和简要说明:

  1. int event_dispatch(void);

event_dispatch函数无需参数,它的作用是启动事件循环,使事件处理器开始监听注册的事件。一旦事件循环启动,它会不断地监听注册的事件,当事件发生时,调用相应的回调函数进行处理。事件循环会持续运行,直到所有事件处理完成或者手动停止事件循环。也就是说,event_dispatch 内部其实是个死循环,会一直监听事件,如果没有事件可监听了,则会退出循环;

5、 event_get_supported_methods()

获取当前支持的方法有哪些,该函数返回一个数组,用法

  1. const char **methods = event_get_supported_methods();
  2. for (int i = 0; methods[i] != NULL; ++i) {
  3. printf("支持的方式:%s\n",methods[i]);
  4. methods ++;
  5. }

打印结果

  1. 支持的方式:epoll
  2. 支持的方式:select

6、event_base_get_method(base)

获取当前使用的多路复用技术,用法

  1. const char *method = event_base_get_method(base);
  2. printf("Using event method: %s\n", method);

打印结果

  1. Using event method: epoll

7、event_base_get_features()

event_base_get_features 函数是 libevent 库中用于获取 event_base 对象所支持的特性的函数,定义如下

  1. int event_base_get_features(const struct event_base *base){
  2. if (base == NULL)
  3. return (0);
  4. return (base->evsel->features);
  5. }

该函数接受一个 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 对象时所需的事件处理特性。它的定义如下:

  1. void event_config_require_features(struct event_config *cfg, int features){
  2. cfg->require_features |= features;
  3. }

该函数接受两个参数:

  • 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 对象的函数。并使用默认的配置,它的定义如下:

  1. struct event_config * event_config_new(void){
  2. struct event_config *cfg = mm_calloc(1, sizeof(struct event_config));
  3. if (cfg == NULL)
  4. return NULL;
  5. /* 初始化 event_config 对象的各个成员变量 */
  6. cfg->n_backends = 0;
  7. cfg->avoid_method = NULL;
  8. cfg->require_features = 0;
  9. cfg->disable_features = 0;
  10. cfg->num_cpus = 0;
  11. cfg->max_dispatch_interval = 0;
  12. cfg->max_exact_secs = 0;
  13. cfg->max_dispatch_callbacks = 0;
  14. return cfg;
  15. }

下面是 event_config_new() 函数的主要功能:

  1. 使用 mm_calloc() 函数分配一块内存来存储 event_config 对象。
  2. 初始化 event_config 对象的各个成员变量。

event_config 对象是用于配置 event_base 对象的一种机制。它可以用来指定事件处理机制的特性、CPU 核心数、最大事件分发间隔等参数。这些参数将在创建 event_base 对象时被使用。

需要注意的是,event_config 是在 event_config_new 函数内动态分配了内存空间的,所以使用完成后一定要用 event_config_free 函数进行释放

  1. // 用完之后一定要释放 event_config
  2. 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

  1. struct event_base * vent_base_new(void) {
  2. return event_base_new_with_config(NULL);
  3. }

该函数直接创建一个新的 event_base 对象,不使用任何 event_config 对象进行配置。它会使用 libevent 库默认的配置参数来创建 event_base 对象。

10.2、event_base_new_with_config

  1. struct event_base * vent_base_new_with_config(const struct event_config *cfg){
  2. struct event_base *base;
  3. /* 根据 event_config 对象的配置创建 event_base 对象 */
  4. base = event_base_new_with_method(cfg->avoid_method,
  5. cfg->require_features,
  6. cfg->disable_features,
  7. cfg->num_cpus,
  8. cfg->max_dispatch_interval,
  9. cfg->max_exact_secs,
  10. cfg->max_dispatch_callbacks);
  11. return base;
  12. }

该函数接受一个 event_config 对象作为参数,根据该对象的配置创建一个新的 event_base 对象。它会使用 event_config 对象中设置的各种参数,如事件处理机制、CPU 核心数、最大事件分发间隔等,来创建 event_base 对象。

11、event_new()

该函数的作用是创建一个新的 event 对象,并将其与指定的 event_base 对象、文件描述符、事件类型和回调函数关联起来。它内部调用了 event_assign 函数来完成实际的初始化工作。它的定义如下:

  1. struct event * event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn cb, void *arg){
  2. return event_assign(NULL, base, fd, events, cb, arg);
  3. }

该函数接受以下参数:

  • base: 一个指向 event_base 对象的指针,用于指定事件处理机制。
  • fd: 要监听的文件描述符。
  • events: 要监听的事件类型,可以是以下值的按位或:
    • EV_READ: 监听读事件。
    • EV_WRITE: 监听写事件。
    • EV_SIGNAL: 监听信号事件。
    • EV_PERSIST: 设置事件为持久型,即事件触发后不会自动从事件队列中移除。
  • cb: 事件触发时要调用的回调函数,该函数需要满足以下原型:
    1. 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 函数的定义如下:

  1. int event_dispatch(void) {
  2. return event_base_dispatch(event_base_get_default());
  3. }

这个函数内部调用了 event_base_get_default() 函数来获取默认的 event_base 对象,然后再调用 event_base_dispatch 函数启动事件循环。它是一个便捷函数,用于在没有自定义 event_base 对象的情况下启动事件循环。

12.2、event_base_dispatch

event_base_dispatch 函数的定义如下:

  1. int event_base_dispatch(struct event_base *event_base)
  2. {
  3. return event_base_loop(event_base, EVLOOP_DEFAULT);
  4. }

这个函数内部调用了 event_base_loop 函数来启动事件循环,并传递了 EVLOOP_DEFAULT 作为事件循环的行为标志。

与 event_dispatch 函数不同的是, event_base_dispatch 函数要求您显式地传入一个 event_base 对象,而不是使用默认的 event_base 对象。这使得您可以更好地控制事件循环的行为,例如可以使用不同的事件循环标志来更改事件循环的行为。

13、event_base_free()

event_base_free 函数是 libevent 中用于释放 event_base 对象的函数。它的定义如下:

  1. void event_base_free(struct event_base *event_base){
  2. event_base_free_nofinalize(event_base, 0);
  3. }

该函数内部调用了 event_base_free_nofinalize 函数来完成实际的释放操作。

event_base_free_nofinalize 函数的定义如下:

  1. void event_base_free_nofinalize(struct event_base *event_base, int flags) {
  2. if (!event_base)
  3. return;
  4. /* 停止事件循环 */
  5. event_base_loopbreak(event_base);
  6. /* 释放与 event_base 关联的资源 */
  7. event_base_free_everything(event_base);
  8. /* 释放 event_base 对象本身 */
  9. mm_free(event_base);
  10. }

该函数主要完成以下几个步骤:

  1. 停止事件循环: 首先调用 event_base_loopbreak 函数来停止事件循环,确保所有事件处理完毕。
  2. 释放资源: 接下来调用 event_base_free_everything 函数来释放与 event_base 对象关联的各种资源,包括事件、信号、定时器等。
  3. 释放 event_base 对象: 最后使用 mm_free 函数释放 event_base 对象本身。
  4. 需要注意的是,在释放 event_base 对象之前,需要先将所有与之关联的事件、信号等资源全部释放掉,否则可能会引发内存泄漏或其他问题。

13、event_del()

event_del 函数的作用是将指定的事件对象从事件循环中移除,停止监听相应的事件类型,并且不再触发对应的回调函数。调用 event_del 后,该事件对象的生命周期并没有结束,可以继续使用 event_add 将其添加回事件循环中,或者使用 event_free 来释放资源。

函数签名如下:

  1. 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函数进行释放。

函数签名如下:

  1. 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 回调函数结构如下

  1. 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 函数的作用是释放指定的套接字监听器对象,并清理其相关资源,包括关闭监听套接字、停止监听等。

函数签名如下:

  1. void evconnlistener_free(struct evconnlistener *lev);

参数 lev 是指向要释放的套接字监听器对象的指针。

调用 evconnlistener_free 函数可以释放指定的套接字监听器对象,释放相关资源,包括关闭监听套接字,并且停止监听。在不需要监听新连接事件时,可以调用该函数来释放监听器对象,以避免资源泄漏。

总之,evconnlistener_free 函数用于释放和销毁一个套接字监听器对象,清理其相关资源,包括关闭监听套接字、停止监听等。

三、缓冲区相关函数

14、bufferevent_read()

bufferevent_read函数是libevent库中用于从一个bufferevent中读取数据的函数。其原型为:

  1. 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中写入数据的函数。其原型为:

  1. 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中输入缓冲区的函数。其原型为:

  1. 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中输出缓冲区的函数。其原型为:

  1. 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缓冲区中移除数据的函数。其原型为:

  1. 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缓冲区中添加数据的函数。其原型为:

  1. 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缓冲区中当前有效数据长度的函数。其原型为:

  1. 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事件回调函数的函数。其原型为:

  1. 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 对象发生状态变化时被调用。

函数原型如下:

  1. 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事件的函数。其原型为:

  1. 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结构中特定事件的函数。其原型为:

  1. 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实例的函数。其原型为:

  1. 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实例,以避免内存泄漏。

关键字后端