muduo对描述符fd,需要监听的事件events,当fd被激活调用的可读/可写/关闭/错误回调函数进行了封装,实现在Channel
类中,Poller
监听的其实就是一个个Channel
对象,Channel
可以向Poller
注册自己关心的事件,当被激活后调用相应的回调函数。类似libevent的struct event。
Channel在整个事件驱动循环中的流程大致如下
- Acceptor接收到客户端请求,调用TcpServer回调函数
- TcpServer回调函数中创建TcpConnection对象,代表着一个Tcp连接
- TcpConnection构造函数中创建Channel对象,保存客户端套接字fd和关心的事件(可读)
- Channel注册自己到所属事件驱动循环(EventLoop)中的Poller上
- Poller开始监听,当发现Channel被激活后将其添加到EventLoop的激活队列中
- EventLoop在poll返回后处理激活队列中的Channel,调用其处理函数
- Channel在处理函数中根据被激活的原因调用不同的回调函数(可读/可写等)
其中
- Acceptor,监听类,用于监听客户端请求,然后接收客户端
- TcpServer,服务器类,用于管理所有的TcpConnection
- TcpConnection,Tcp连接类,代表一个Tcp连接,内部保存对应的Channel
- Channel,套接字和相应事件及回调函数的封装,一个事件类
- Poller,io复用的封装,用于监听Channel
- EventLoop,事件驱动主循环,调用poll函数,管理激活队列,类似libevent的struct event_base
函数对象std::function
C++基于对象其实就是利用std::function/std::bind
实现的,作用是绑定某个类的函数指针
使用方法如
#include <functional>
typedef std::function<void()> Callback;
void function_bind_test(Callback func)
{
func();/* 这里调用相当于conn->connectionEstablished() */
}
function_bind_test(std::bind(&TcpConnection::connectionEstablished, conn));
std::function/std::bind
为类的成员函数的调用提供更多灵活性,在C++11引入lambda
后逐渐取代了std::bind
,C++14后lambda
支持模板参数后完全取代了std::bind
Channel定义如下,成员函数主要就是
- 设置回调函数
set*Callback
- 设置对fd关心的事件,将自己存储的fd及相应的事件注册到Poller中
enable*
- 删除对fd的监听,将其从
Poller
的ChannelMap
中移除disableAll
- 被激活时调用的回调函数
hanleEvent
/*
* Channel其实就是一个事件类,保存fd和需要监听的事件,以及各种回调函数
* 类似libevent的struct event
*/
class Channel : noncopyable
{
pu