关于libevent库的一些看法
libevent库结合了epoll、poll、select等处理并发事件的应对方法,其中针对不同的应用场景,提出了两类事件框架:event和bufferevent。
这两类事件框架的本质区别在于是否具有缓冲区。
如何理解这个区别?
首先需要认识到这个缓冲区在整个流程中起到一个什么作用。——不错,就是数据交换,无血缘关系的进程之间的信息交换!
那么对于能通过文件描述符,利用内核共享数据的情况下,使用event结构,是最高效的;相比而言,若所涉及的情形下,无法利用通过内
核共享读写缓存时,这时候使用libevent中的bufferevent就是个最好的选择了。
基于event事件的程序流程如下:
- 首先建立一个event_base框架
- 随后,定义event事件
- 将event事件加入到框架中
- 执行消息循环
- 释放资源
对于第一点,在新建任务时,若不特殊著名EV_PERSIST,则程序只激活一次或认为被检测一次,随后将被从框架中取下。
对于第二点,会用到文件描述符,因此,在实现第二点之前,应得到用于进程通讯的文件描述符,可以是管道,输入输出流等等;其实整个过程可以看作是对文件描述符的一个包装,即将文件描述符包装成一个event。
对于第三点,若指定时间,则程序及时没有得到响应,但时间一到,仍然会调用回调函数。
基于bufferevent时间的程序流程如下:
由于基于bufferevent事件时其实现过程类似与socket通信,故其实现将分为服务器端与客户端两个版本
服务器端
首先建立一个event_base框架
后面有两种实现方式:
(方式一)
- 使用socket,获得监听文件描述符,此时可以设置端口复用
- 利用得到的文件描述符,定义bufferevent事件
- 开启事件的读缓冲区
- 设置事件的回调函数
- 借由定义的bufferevent事件,定义连接监听器
- 设置连接监听器的回调函数
- 消息循环
- 资源释放
(方式二)
- 直接定义连接监听器,创建带绑定的那个
- 设置连接监听器的回调函数
- 在回调函数中会得到通讯套接字,定义bufferevent事件
- 开启事件的读缓冲区
- 设置事件的回调函数
- 利用得到的通讯套接字,
- 消息循环
- 资源释放
这里需要说明一下,对于写事件的回调函数,是在对写缓冲区写入的时候生效,故若读事件中包含有对写缓冲区的操作,则会在写缓冲区之后,立即调用写回调,随后才会往下执行。
客户端
首先建立一个event_base框架
随后也有两种操作
(方式一)
- 调用socket得到文件描述符
- 再利用该文件描述符建立bufferevent事件
- 设置事件的回调函数,并开启读缓冲区
- 利用得到的bufferevent事件进行连接
- 设置事件循环
- 释放资源
(方式二)
- 直接创建bufferevent事件,文件描述符位置填入-1,此时函数会自动创建一个文件描述符,并设置为非阻塞
- 设置事件的回调函数,并开启读缓冲区
- 利用得到的bufferevent事件进行连接
- 设置事件循环
- 释放资源