Muduo库设计(6)——Tcp断开连接

Muduo只有一种关闭连接的方式:被动关闭,即对方先关闭连接
当TcpConnection在处理读事件时(handleRead),当read接口返回的长度为0时,触发关闭逻辑。

void TcpConnection::handleRead()
{
  char buf[65536];
  ssize_t n = ::read(channel_->fd(), buf, sizeof buf);
  if (n > 0) {
    messageCallback_(shared_from_this(), buf, n);
  } else if (n == 0) {        //n为0,表明对方已关闭连接
    handleClose();
  } else {
    handleError();
  }
}

handleClose通知TcpServer关闭连接

void TcpConnection::handleClose()
{
  loop_->assertInLoopThread();
  assert(state_ == kConnected);
  // we don't close fd, leave it to dtor, so we can find leaks easily.
  channel_->disableAll();
  // 通知TcpServer关闭连接
  closeCallback_(shared_from_this());
}

TcpServer先在map中删除该连接对应的键值对,然后再通知EvevtLoop对象调用TcpConnection::connectDestroyed方法

void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
  loop_->assertInLoopThread();
  size_t n = connections_.erase(conn->name());
  loop_->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));
}

connectDestroyed先关闭对channel上的事件的监听,然后通知上层连接已关闭,最后删除poller对象中的channel对象

void TcpConnection::connectDestroyed()
{
  loop_->assertInLoopThread();
  assert(state_ == kConnected);
  setState(kDisconnected);
  channel_->disableAll();                  //关闭掉channel对事件的监听
  connectionCallback_(shared_from_this());   //通知上层连接已关闭

  loop_->removeChannel(channel_.get());    //删除poller对象中的channel
}

Poller对象中删除channel对象的逻辑如下:

void Poller::removeChannel(Channel* channel)
{
  assertInLoopThread();

  int idx = channel->index();
  const struct pollfd& pfd = pollfds_[idx];
  size_t n = channels_.erase(channel->fd());            //1、先删除map中的键值对
  if (implicit_cast(idx) == pollfds_.size()-1) {
    pollfds_.pop_back();                                //2、如果在vector尾部直接删除
  } else {
    int channelAtEnd = pollfds_.back().fd;              //3、如果不在尾部,先与尾部元素交换后再删除,避免了vector中元素的移动
    iter_swap(pollfds_.begin()+idx, pollfds_.end()-1);
    if (channelAtEnd < 0) {
      channelAtEnd = -channelAtEnd-1;
    }
    channels_[channelAtEnd]->set_index(idx);
    pollfds_.pop_back();
  }
}

你可能感兴趣的:(Muduo库设计(6)——Tcp断开连接)