Muduo之TcpConnection源码分析笔记

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的地方静静地等待下一个连接的到来。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值