libevent将它所看到的一切都看做事件来处理,这次我们经常使用的读写缓冲区也未能幸免。那么为什么libevent会把读写缓冲区加入到它的事件机制中呢?在回答这个问题之前,首先看一下客户端网络套接口的读写事件。我们用一段话来描述它:
客户端创建套接口,对套接口进行设置,然后调用connect连接到服务器端。如果连接成功,并且套接口可读、可写或者发生错误,那我们就执行相应的操作。
那么像网络套接口读写这样的事件,libevent是如何去实现或者支持的呢?下面,我们就来看一下libevent事件机制的实现。
libevent事件机制通常由四部分组成:
(1)事件对象
(2)事件对象的触发条件
(3)针对事件对象的操作
(4)事件对象的配置
事件对象是事件机制的核心,整个机制都是建立在其基础之上的。那么在网络套接口读写事件中,网络套接口就是该事件的对象,整个网络套接口的操作都针对网络套接口进行的。
事件对象的触发条件是指在某种指定的情况下,使得该事件对象能够进行某种操作。比如说当网络套接口可读。
当满足某种指定的条件时,就触发相应的操作,比如读写网络套接口
事件对象本身具有的某些属性可以通过相应的配置函数来设置。比如设置套接口的低潮限度。
同样,对于读写缓冲区而言,其所有具有的性质和网络套接口一样,同样可以把它当做一个libevent事件,将其纳入到libevent的事件机制中来管理。但是其又与网络套接口、时间、信号这些事件不一样。有什么不一样呢,在libevent中专门为buffer事件定义了结构体和围绕该结构体上的一系列操作。现在有一个问题,为什么libevent不专门为网络套接口或者时间或者信号也定义这种专门针对自身的结构体呢?这取决于buffer的特殊性。因为buffer在操作系统中没有根。对于网络套接口、时间、信号这些事件都是操作系统支持的并且在其上有很多的操作,那么libevent将这些事件进行抽象可以用一种统一的方式进行表达,然后在底层调用对应的操作系统提供的系统调用即可。但是buffer就不一样了,buffer是用户定义的,对应着操作系统的一块虚拟内存,用户除了对虚拟内存进行读写之外操作系统没有提供额外的接口使用户操作自己定义的buffer。那么既然libevent将其看做一个事件,那么就需要提供一套围绕这个事件的操作。既然操作系统没有提供底层的接口(也不可能提供),那么libevent就要自己去实现,然后以bufferevent的方式呈现出来。
在下一节我们将看到如何使用bufferevent。