muduo网络库源码复现笔记(二十三):TcpConnection断开连接

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();
}

猜你喜欢

转载自blog.csdn.net/MoonWisher_liang/article/details/107639147