Muduo网络库简介
muduo 是一个基于 Reactor 模式的现代 C++ 网络库,作者陈硕。它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。
muduo网络库的核心代码只有数千行,在网络编程技术学习的进阶阶段,muduo是一个非常值得学习的开源库。目前我也是刚刚开始学习这个网络库的源码,希望将这个学习过程记录下来。这个网络库的源码已经发布在GitHub上,可以点击这里阅读。目前Github上这份源码已经被作者用c++11重写,我学习的版本是没有使用c++11版本的。不过二者大同小异,核心思想是没有变化的。点这里可以看我的源代码。从笔记十七开始记录muduo的net库的实现过程。如果你需要看一下基础库(base)的复现过程,可以点击这里:muduo的base库实现过程。而网络库的笔记在这里:
muduo网络库源码复现笔记(十七):什么都不做的EventLoop
muduo网络库源码复现笔记(十八):Reactor的关键结构
muduo网络库源码复现笔记(十九):TimeQueue定时器
muduo网络库源码复现笔记(二十):EventLoop::runInloop()函数和EventLoopThread类
muduo网络库源码复现笔记(二十一):Acceptor类、InetAddress类、Sockets类、SocketsOps.cc
muduo网络库源码复现笔记(二十二):TcpServer类与TcpConnection初步
TcpConnection断开连接
上一节的内容介绍了muduo如何创立一个Tcp连接,但没有讲如何断开连接。muduo断开连接的方式是接受客户端断开连接的消息,然后通过控制智能指针的生命周期来实现断开连接。时序图如下图所示,下面我们具体分析一下。
如图所示,当客户端断开连接后,channel调用handleRead函数读取数据,读取字节数n == 0,这时调用handleClose函数来处理断开连接。handleClose会调用TcpConnection的closecallback,在创建TcpConnection时会被TcpServer绑定为removeConnection。
void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
loop_ -> assertInLoopThread();
LOG_INFO << "TcpServer::removeConnctionInLoop [" << name_
<< "] - connection " << conn -> name();
LOG_TRACE << " [8] usecount = " << conn.use_count();
size_t n = connections_.erase(conn->name());
LOG_TRACE << " [9] usecount = " << conn.use_count();
(void)n;
assert(n == 1);
loop_ -> queueInLoop(
boost::bind(&TcpConnection::connectDestroyed,conn));
LOG_TRACE << " [10] usecount = " << conn.use_count();
}
removeConnection将当前TcpConnection从TcpServer的map中去掉,然后将connectionDestroyed加入loop的任务队列,这时handleClose函数就结束了,随后loop循环调用connectionDestroyed函数将Channel从poller中去掉,注意这里我们传递了一个管理TcpConnection的智能指针conn过去,这样做的目的是延长TcpConnection的生命周期到调用connectionDestroyed。如有兴趣可以根据日志跟踪一下管理TcpConnection智能指针的use_count()。
void TcpConnection::connectDestroyed()
{
loop_ -> assertInLoopThread();
if(state_ == kConnected)
{
setState(kDisconnected);
channel_->disableAll();
connectionCallback_(shared_from_this());
}
channel_ -> remove();
}