Muduo之TcpConnection源码分析笔记

xiaoxiao2021-02-27  204

Muduo之TcpConnection源码分析笔记

上一节中我们分析到当TcpServer(Acceptor)检测到读事件时,就会创建一个TcpConnection对象,那么这里我们就分析下TcpConnection的细节。

首先我们看下TcpConnection的类数据成员:

以及如下是TcpConnection的构造函数:(PS:其实我们假象认为TcpConnection就是一个socket和一大堆回调函数的集合,代表一个和对端的TCP连接,而TcpConnection里面自然包含了Channel和EventLoop对象)

TcpConnection::TcpConnection(EventLoop* loop, const string& nameArg, int sockfd, const InetAddress& localAddr, const InetAddress& peerAddr) : loop_(CHECK_NOTNULL(loop)), name_(nameArg), state_(kConnecting), reading_(true), socket_(new Socket(sockfd)), channel_(new Channel(loop, sockfd)), localAddr_(localAddr), peerAddr_(peerAddr), highWaterMark_(64*1024*1024) { channel_->setReadCallback( boost::bind(&TcpConnection::handleRead, this, _1)); channel_->setWriteCallback( boost::bind(&TcpConnection::handleWrite, this)); channel_->setCloseCallback( boost::bind(&TcpConnection::handleClose, this)); channel_->setErrorCallback( boost::bind(&TcpConnection::handleError, this)); LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this << " fd=" << sockfd; socket_->setKeepAlive(true); }

从上面的类图可以大概的知道TcpConnection拥有的数据成员,图中省略了一些public接口。

因为TcpConnection是当有连接请求的时候创建的,那么就应该有相应的socket fd。

而在构造函数中我们可以看到创建了Channel对象,之前我们说过Channel是对socket以及回调函数的封装,Acceptor里面都有channel,那么针对TcpConnection也应该有该socketfd以及回调函数的封装,初始化Channel的过程就是将socket和looper关联的过程。另外构造函数中前几句都是对于channel对象中回调函数的一些初始化。那么当TcpConnection创建完成之后又怎么样了呢?我们看到在TcpServer::newConnection()里面最后有这么一句话:

ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn));

我们看到这里将新建的TcpConnection加入到了选区的EventLoop任务队列里面。我们看下EventLoop::runInLoop()的代码可以知道这里执行上就是调用了TcpConnection::connectEstablished()。我们来看下它的代码:

void TcpConnection::connectEstablished() { loop_->assertInLoopThread(); assert(state_ == kConnecting); setState(kConnected); channel_->tie(shared_from_this()); channel_->enableReading(); connectionCallback_(shared_from_this()); }

因为连接这时候是处于accept()之后的因此状态是kConnected,我们可以看到channel->enableReading()。而这句代码就是将该Channel加入到EventLoop当中去的。 这个因为涉及到Channel的方法我们在之后的内容里面讲解。

总结

当TcpServer::newConnection()创建了TcpConnection之后并调用EventLoop::runInLoop()之后就将该Channel加入到了EventLoop当中去了。之后所有该连接的操作都是由该EventLoop所属的线程处理,Acceptor不再控制,它又回到之前的poll的地方静静地等待下一个连接的到来。

转载请注明原文地址: https://www.6miu.com/read-11061.html

最新回复(0)