您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

muduo各个类梳理

文章目录

    • 一、Channel类
    • 二、Poller/EpollPoller类
    • 三、EventLoop类
    • 四、Thread、EventLoopThread、EventLoopThreadPool类
    • 五、Acceptor类
    • 六、Buffer类
    • 七、TcpConnection类
    • 八、TcpServer类

在这里插入图片描述
mainReactor就是我们代码中的mainloop(baseloop),subReactor是我们代码中的工作线程进行读写事件的处理,read是底层做的,decode、compute、encode是用户做的。从网络上read数据,然后从网络上send数据,这些是由muduo库的。decode、compute、encode是用户在OnMessage处理的业务逻辑,每一个线程执行一个独立的Reactor

muduo库的核心模块包括:Channel、Poller/EpollPoller、EventLoop、Thread、EventLoopThread、EventLoopThreadPool、Socket、Acceptor、Buffer、TcpConnection、TcpServer

一、Channel类

在这里插入图片描述

Channel主要是封装了以下成员:

  • fd_:需要注册在Poller(poll/epoll)的用于和用户通信的文件描述符
  • events_:fd感兴趣的事件
  • revents_:fd发生的事件
  • loop_:Channel归属的事件循环EventLoop
  • callback_:发生事件时,根据Poller通知的revents执行的回调函数
  • index_:用于标识Chnnel的状态

在这里插入图片描述
我们总共只有两种Channel(acceptorChannel和connChannel),因为总共只有两种fd,分别是用于监听新用户连接的listenfd和用于监听已连接用户读写事件的connfd

二、Poller/EpollPoller类

相当于是事件分发器Demultiplex
在这里插入图片描述
Poller封装了以下成员:

  • channels_:一个事件循环EventLoop中包含一个Poller,这个Poller负责管理channels_,负责监听这些channels_上的事件,有事件发生时,会把有事件发生的Channel放入EventLoop::activateChannels_,然后ownerLoop_通过activateChannels_调用处理事件的回调。Channel和Poller不能直接通信,通过EventLoop通信
  • ownerLoop_:Poller所属的EventLoop,Poller会填充有事件发生的Channel到ownerLoop_的成员到activateChannels_
void EventLoop::loop(){
    looping_ = true;
    quit_ = false;

    LOG_INFO("EventLoop %p start looping \n", this);

    while(!quit_){
        activateChannels_.clear();
        pollReturnTime_ = poller_->poll(kPollTimeMs, &activateChannels_);
        // for循环处理所有发生事件的channel
        for(Channel* channel : activateChannels_){
            // poller监听哪些channel发生事件,然后上报给EventLoop,EventLoop通知channel调用相应的回调函数处理相应的事件(Channel执行回调)
            channel->handleEvent(pollReturnTime_);
        }
        // subReactor给唤醒后,执行需要处理的回调操作(mainReactor事先注册的),接收新用户的Channel
        doPendingFunctors();
    }

    LOG_INFO("EventLoop %p stop loop \n", this);
    looping_ = false;
}

三、EventLoop类

在这里插入图片描述

  • activateChannels_:包含了所有发生事件的Channel,Poller会把有事件发生的Channel放入EventLoop::activateChannels
  • wakeupFd_和wakeupChannel_:一个wakeupFd_隶属于一个EventLoop,每一个wakeupFd_都是注册在了EventLoop管理的Poller上。对于subloop来说,wakeupChannel_用于和mainloop通信,activateChannels用于已连接的客户端通信,如果activateChannels没有事件发生,subloop就会一直阻塞监听,而此时有新的客户连接,mainloop需要找一个subloop处理这个已连接用户的读写事件,就需要往这个subloop的wakeupFd_上写8字节数据唤醒
  • pendingFunctors_:每一个回调函数都需要在发生事件的EventLoop所属的线程执行,如果当前loop是属于当前执行的线程,那直接执行回调函数,否则就把回调函数存到pendingFunctors这个vector里面,然后唤醒相应loop所在线程。然后被唤醒的线程会执行在pendingFunctor里所有的函数

在这里插入图片描述

四、Thread、EventLoopThread、EventLoopThreadPool类

EventLoopThreadPool类的成员如下:
在这里插入图片描述
getNextLoop方法:通过轮询算法获取下一个subloop,如果用户没有使用setThreadNum设置subloop线程的数量,那就没有创建subloop,getNextLoop返回的一直是baseloop

EventLoopThread类的成员如下:
在这里插入图片描述
EventLoopThread封装了线程Thread以及对应的事件循环EventLoop,Thread封装了std::thread

Thread类的成员如下:
在这里插入图片描述
TcpServer启动的时候,会让自己的成员threadPool_也启动
在这里插入图片描述
线程池启动时,会创建事件循环线程EventLoopThread,让该EventLoopThread调用startLoop方法
在这里插入图片描述
接着会让事件循环对应的Thread类线程启动
在这里插入图片描述
这里的thread_.start方法就会调用thread_生成时传入的回调函数,即EventLoopThread::threadFunc
在这里插入图片描述
这样就启动了事件循环,即epoll_wait开始监听事件

五、Acceptor类

在这里插入图片描述

  • loop_:Acceptor所属的事件循环,即mainLoop
  • acceptSocket_、acceptChannel_:封装了listenfd,用于监听新用户连接

Acceptor工作在mainLoop,主要封装了listenfd相关操作,包括创建socket、bind、listen

六、Buffer类

Buffer类的成员如下:
在这里插入图片描述

缓冲区里有kCheapPrepend、readeridx、writeridx,这3个成员,[readeridx, writeridx]表示可读数据区间

prependable有8个字节,是头部信息,用于记录数据包的长度,刚开始readeridx和writeridx都在这8个字节处的位置,然后我们写数据进去,写好的东西就可以是待发送的东西,由Buffer专门进行在缓冲区读取数据进行发送,我们从缓冲区可以进行send发送,用户也可以不断从缓冲区读取数据,通过readeridx和writeridx处理

Buffer是缓冲区,对于nonblocking(非阻塞)的I/O,我们都需要设置缓冲区,涉及到应用写数据写到缓冲区,write函数将应用程序缓冲区的数据再写到TCP的发送缓冲区,最后发送数据

如果应用程序调用write直接写入TCP的发送缓冲区,写满了就要发送,应用程序就要暂停写入等待发送完成,这是同步的过程,效率比较慢。 如果有缓冲区的话,应用程序可以随意的向应用程序缓冲区写数据,等TCP缓冲区空了Buffer再将应用程序缓冲区中的数据写入TCP缓冲区

应用产生数据快,tcp发送的慢,难道每一次发送数据都要等tcp发送完上一次的数据再发送当前数据?

写数据到Buffer,然后让系统去调用write从Buffer写入TCP发送缓冲区,或者系统调用read从TCP接收缓冲区写入Buffer。相当于应用发送或者接收数据和tcp真实发送或者接收数据就成异步的了,这样非常高效

七、TcpConnection类

在这里插入图片描述
封装了socket,Channel,和一系列回调操作,高水位线的控制(不要发送过快),发送和接收缓冲区

对于Channel执行的回调,都是由TcpConnection来设置的

八、TcpServer类

在这里插入图片描述


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进