10、《Libevent中文帮助文档》学习笔记10:Bufferevent概念和入门

很多时候,除了响应事件之外,应用还希望做一定的数据缓冲。比如说,写入数据的时候,通常的运行模式是:

  • 决定要向连接写入一些数据,把数据放入到缓冲区中;
  • 等待连接可以写入;
  • 写入尽量多的数据;
  • 记住写入了多少数据,如果还有更多数据要写入,等待连接再次可以写入;

这种缓冲IO模式很通用,libevent为此提供了一种通用机制,即bufferevent。bufferevent由一个底层的传输端口(如套接字)、一个读取缓冲区、一个写入缓冲区组成。与通常的事件在底层传输端口已经就绪,可以读取或者写入的时候执行回调不同的是,bufferevent在读取或者写入了足够量的数据之后调用用户提供的回调。有多种共享公用接口的bufferevent类型,编写本文时已存在以下类型:

  • 基于套接字的bufferevent:使用event_*接口作为后端,通过底层流式套接字发送或者接收数据的bufferevent;
  • 异步IObufferevent:使用Windows IOCP接口,通过底层流式套接字发送或者接收数据的bufferevent(仅用于Windows,试验中);
  • 过滤型bufferevent:将数据传输到底层bufferevent对象之前,处理输入或者输出数据的bufferevent;比如说,为了压缩或者转换数据;
  • 成对的bufferevent:相互传输数据的两个bufferevent;

注意:截止2.0.2-alpha版,这里列出的bufferevent接口还没有完全正交于所有的bufferevent类型。也就是说,下面将要介绍的接口不是都能用于所有bufferevent类型,libevent开发者在未来版本中将修正这个问题。

也请注意:当前bufferevent只能用于像TCP这样的面向流的协议,将来才可能会支持像UDP这样的面向数据报的协议。

本节描述的所有函数和类型都在event2/bufferevent.h中声明。特别提及的关于evbuffer的函数声明在event2/buffer.h中,详细信息请参考下一章。

1 bufferevent和evbuffer

每个bufferevent都有一个输入缓冲区和一个输出缓冲区,它们的类型都是"struct evbuffer"。有数据要写入到bufferevent时,添加数据到输出缓冲区;bufferevent中有数据供读取的时候,从输入缓冲区抽取(drain)数据。evbuffer接口支持很多种操作,后面的章节将讨论这些操作。

2 回调和水位

每个bufferevent有两个数据相关的回调:一个读取回调和一个写入回调。默认情况下,从底层传输端口读取了任意量的数据之后会调用读取回调;输出缓冲区中足够量的数据被清空到底层传输端口后写入回调会被调用。通过调整bufferevent的读取和写入"水位(watermarks)"可以覆盖这些函数的默认行为。

每个bufferevent有四个水位:

  • 读取低水位:读取操作使得输入缓冲区的数据量在此级别或者更高时,读取回调将被调用。默认值为0,所以每个读取操作都会导致读取回调被调用。即:只要从底层IO缓冲区读取数据后,bufferevent输入缓冲区中会有数据,导致数据量大于低水位0,导致读取回调被调用;这里说的读取是针对底层IO缓冲区
  • 读取高水位:输入缓冲区中的数据量达到此级别后,bufferevent将停止读取,直到输入缓冲区中足够量的数据被抽取,使得数据量低于此级别。默认值是无限,所以永远不会因为输入缓冲区的大小而停止读取。高水位是防止bufferevent输入缓冲区数据过多导致溢出,因此数据量到达高水位后,会停止从底层IO中读取数据,实际不存在这种情况;这里说的读取是针对底层IO缓冲区
  • 写入低水位:写入操作使得输出缓冲区的数据量达到或者低于此级别时,写入回调将被调用。默认值是0,所以只有输出缓冲区空的时候才会调用写入回调。写入操作是将bufferevent输出缓冲区中的数据写入到底层IO,写入后,bufferevent输出缓冲区数据量会减少,如果剩余数据量等于低水位,表示数据都写完了,写入回调被调用;这里说的写入是针对底层IO缓冲区
  • 写入高水位:bufferevent没有直接使用这个水位。它在bufferevent用作另外一个bufferevent的底层传输端口时有特殊意义。请看后面关于过滤型bufferevent的介绍;这里说的写入是针对底层IO缓冲区

bufferevent也有"错误"或者"事件"回调,用于向应用通知非面向数据的事件,如连接已经关闭或者发生错误。定义了下列事件标志:

  • BEV_EVENT_READING:读取操作时发生某事件,具体是哪种事件请看其他标志。
  • BEV_EVENT_WRITING:写入操作时发生某事件,具体是哪种事件请看其他标志;
  • BEV_EVENT_ERROR:操作时发生错误。关于错误的更多信息,请调用EVUTIL_SOCKET_ERROR();
  • BEV_EVENT_TIMEOUT:发生超时;
  • BEV_EVENT_EOF:遇到文件结束指示;
  • BEV_EVENT_CONNECTED:请求的连接过程已经完成;

3 延时回调

默认情况下,buffe

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Libevent是一个事件驱动的网络编程框架,而event.h是其核心头文件之一。该头文件定义了事件处理相关的结构体、函数和宏等内容。 下面是event.h中常用的一些定义和函数: ### 1.事件回调函数 ```c typedef void (*event_callback_fn)(evutil_socket_t fd, short events, void *arg); ``` 该类型定义了事件回调函数的原型,其中fd是事件所在的文件描述符,events是事件类型,arg是用户传入的参数。 ### 2.事件结构体 ```c struct event { event_callback_fn ev_callback; // 事件回调函数 int ev_fd; // 事件所在的文件描述符 short ev_events; // 事件类型 short ev_res; // 事件结果 struct event_base *ev_base; // 事件所属的event_base void *ev_arg; // 用户传入的参数 }; ``` 该结构体表示一个事件,其中ev_callback是事件回调函数,ev_fd是事件所在的文件描述符,ev_events是事件类型,ev_res是事件结果,ev_base是事件所属的event_base,ev_arg是用户传入的参数。 ### 3.事件类型 ```c #define EV_TIMEOUT 0x01 #define EV_READ 0x02 #define EV_WRITE 0x04 #define EV_SIGNAL 0x08 #define EV_PERSIST 0x10 #define EV_ET 0x20 ``` 该宏定义了事件类型,分别为超时事件、读事件、写事件、信号事件、持续事件和边缘触发事件。 ### 4.事件处理函数 ```c struct event_base *event_base_new(void); int event_base_dispatch(struct event_base *base); int event_base_loopexit(struct event_base *base, const struct timeval *tv); void event_base_free(struct event_base *base); ``` 这些函数用于创建event_base、处理事件、退出事件循环和释放event_base等操作。 以上是event.h中的一些常用内容,更多细节可以查看源码和官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值