muduo梳理
Mzy 金丹

Muduo梳理

使用Muduo搭建简单的服务器

  1. 建立事件循环器EventLoop : loop
  2. 建立服务器对象TcpServer :server
  3. TcpServer中注册各类事件的用户自定义的回调函数:onConnection,onMessage
  4. 设置底层线程数量
  5. 启动start函数,server.start()
  6. 开启主线程(mainloop)事件循环loop.loop()

构建TCP对象

TcpServer的构造函数中建立一个Acceptor的对象,在Acceptor的构造函数中创建了一个非阻塞的listenfd,并封装为Channel对象acceptChannel。在Acceptor构造函数中,给acceptChannel设置了一个ReadCallback回调,事件绑定了handleread。当有新用户连接到来时,Poller监听channel发生事件了,然后上报给EventLoop,通知channel处理相应的事件注册。在底层Channel中的handleEvent就会监控到EPOLLIN事件,并执行相应的readCallback();而对于acceptChannel对应的readCallback()方法,就是执行Accpetor::handleread(),实际上是执行一个newConnectionCallback_()的回调,而newConnectionCallback_()是通过setnewConnectionCallback设置的,而Acceptor是由TcpServer管理的,实际是设置的setnewConnectionCallbackTcpServer::newConnection

acceptChannel注册在事件监听器Poller上,acceptChannel发生可读事件(即新用户连接)就会调用 Acceptor::handleRead

Acceptor::setReadCallback => Acceptor::handleRead => newConnectionCallback

​ ||

TcpServer的构造函数中设置了acceptor->setnewConnectionCallback

​ ||

​ 实际上设置的就是TcpServer::newConnection

注册在mainloop中的acceptor,当有新用户连接到来,最终相应的是TcpServer::newConnection

TcpServer::newConnection()实际是创建了一个TcpConnection的对象

start()方法调用

threadPool_->start(threadInitCallback_); // 启动底层的loop线程池

​ ||

创建loop子线程并开启loop.loop()(子线程)

执行accept::listen()方法,实际上就是将accpetChannel注册在mainloopPoller

开启mainlooploop(为搭建服务器的最后一步)

新用户连接到来

TcpServer::newConnection

​ ||

根据轮询算法,选择一个subLoop,即ioloop

创建了一个TcpConnection对象,注册相应的回调(close的回调对应TcpServer::removeConnection

直接调用TcpConnection::connectEstablished

ioLoop->runInLoop => TcpConnection::connectEstablished,因为设置了子线程数量(如果没有设置子线程数量,之间在mainloop中执行),runInLoop实际调用的是queueInLoop(),执行wakeup(),通过ioloop的指针找到wakeupfd,向wakeupfd写一个数据,wakeupChannel就发生读事件,当前loop线程(即ioloop)就会被唤醒,唤醒后执行connectEstablished()

​ ||

TcpConnection::connectEstablished

poller注册channelepollin事件,然后执行connectionCallback,对应的就是用户自定义的onConnection函数执行成功,就会有socketChannel注册在这个subloop

连接成功后,数据通信

成功建立连接后
||
有可读事件到来,就会执行Channel中的readCallback(),而readCallback()是通过setReadCallback设置的,在TcpConnection中,setReadCallback绑定是TcpConnection::handleRead

​ ||

开始读数据,读完数据后,执行用户自定义的回调操作onMessage,然后就得到原始字符串,进行业务处理,业务处理完进行响应(如:回送消息)

连接关闭

通信异常或者对端关闭,底层channel都会触发closeCallback的回调,而closeCallback()是通过setCloseCallback设置的。在TcpConnection中,setCloseCallback绑定是TcpConnection::handleClose

​ ||

channel_->disableAll(),将chanel所有感兴趣的事件,在poller上全部进行删除,然后执行用户的回调

执行closeCallback_(connPtr),关闭连接的回调 执行的是TcpServer::removeConnection回调方法

​ ||

​ 将保存所有的TcpConnection连接的map删除,然后获取这条连接对应的ioloop,然后执行TcpConnection::connectDestroyed,把channelpoller中删除掉

Powered by Hexo & Theme Keep
Unique Visitor Page View