Muduo
梳理
使用Muduo
搭建简单的服务器
- 建立事件循环器
EventLoop : loop
- 建立服务器对象
TcpServer :server
- 向
TcpServer
中注册各类事件的用户自定义的回调函数:onConnection
,onMessage
- 设置底层线程数量
- 启动
start
函数,server.start()
- 开启主线程(
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
管理的,实际是设置的setnewConnectionCallback
是TcpServer::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
注册在mainloop
的Poller
上
开启mainloop
的loop
(为搭建服务器的最后一步)
新用户连接到来
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
注册channel
的epollin
事件,然后执行connectionCallback
,对应的就是用户自定义的onConnection
函数执行成功,就会有socket
和Channel
注册在这个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
,把channel
从poller
中删除掉