Muduo是由陈硕大佬个人开发的C++网络库,最近在剖析其源码,在此做一些归纳整理。
Muduo网络库的框架模型主要基于Reactor模式,这是一种用于处理多个I/O事件的高效并发模型。
Reactor模式是一种事件驱动的处理模式,它用于同步地派发基于事件或状态的请求到一个或多个服务处理程序。在Muduo中,Reactor模式被用来处理网络I/O事件,如数据的可读、可写以及错误事件。
内含向Poller中注册的文件描述符fd,封装了感兴趣的事件events、Poller返回的发生的事件revents,和一组能够根据fd发生的事件revents进行回调的回调函数callbacks
共有两种Channel,一种是listenfd - acceptorChannel,一种是connfd - connectionChannel
std::unordered_map channels_; // key为fd
通过epollctl把Channel中包含的fd注册到epoll上,当epoll返回时,可以通过fd找到Channel,进而进行相应的回调。
std::vector activeChannels_;
std::unique_ptr poller_;
一个Eventloop管理一堆Channel和一个poller。Channel想注册到poller上或者在poller上修改自己感兴趣的事件,Channel都是通过EventLoop来获取到poller,进而完成相应任务;同时,poller监听到sockfd有相应事件发生,也要通过EventLoop来调用相应Channel的fd的所发生事件的回调函数。
int wakeupFd_; // 一个wakeupfd隶属于一个loop
std::unique_ptr wakeupChannel_;
loop执行的时候,驱动底层的事件分发器Demultiplx也即epoll_wait,若没有事件发送,则loop一定阻塞在epoll_wait上;若是想唤醒某个loop的阻塞状态,那就可以通过loop对象获取其对应的wakeupfd,并往wakeupfd写一点数据,来使loop从epoll_wait上返回,这是因为每一个wakeupfd也封装成了一个wakeupChannel,注册在了底层的epoll上。
std::vector pendingFunctors_;
如果当前线程要调用其他线程中的loop进行回调操作,则将回调函数存放到pendingFunctors_中,并weakup相应的loop。
EventLoop *getNextLoop();
通过轮询算法获取下一个subLoop,如果没有setThreadNum设置多线程,那么获取到的永远是baseLoop;如果有设置过多线程,那么threadPool会驱动底层创建新线程,一个thread对应一个loop,即 one loop per thread
主要封装了listenfd相关操作,socket创建、bind、listen,listen开启后打包成acceptorChannel,放到baseLoop去执行
缓冲区 应用写数据 =》缓冲区 =》 Tcp发送缓冲区 =》 send
+-------------------+------------------+------------------+
| prependable bytes | readable bytes | writable bytes |
| 缓冲区头 | (CONTENT) | 可写空间 |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= size
一个连接成功的客户端对应一个TcpConnection,封装了Socket、Channel和各种回调函数,还有发送和接收缓冲区
封装Acceptor,EventLoopThreadPool,以及
std::unordered_map connections_;