5.muduo之TcpConnection类

介绍:该类起到一个承上启下的作用,维持着TcpServer, Channel, Socket等等之间的练习,后面会通过画图来进行剖析。暂时放下

1.TcpConnection.h文件

///该类对象,客户端和服务器都会用到
///这是一个接口类,所以不用暴露太多细节
class TcpConnection : noncopyable,
                      public std::enable_shared_from_this<TcpConnection>
{
 public:
  /// Constructs a TcpConnection with a connected sockfd
  ///用一个已建立连接成功的sockfd来构造该类对象
  /// 用户不应该自己构造。该类对象会在accept()之后调用一个连接回调函数,在其中会构造一个该类对象

	///从属的loop,I/O线程池有线程时,则是该loop属于其中一个线程的,如果没有时,则就是主线程的
	///loop
  TcpConnection(EventLoop* loop,
                const string& name,	///连接名称
                int sockfd,	///建立连接成功返回的fd
                const InetAddress& localAddr,	///本端地址
                const InetAddress& peerAddr);	///对端地址
  ~TcpConnection();

  EventLoop* getLoop() const { return loop_; }	///返回从属的loop
  const string& name() const { return name_; }	///返回该连接对象的名字
  const InetAddress& localAddress() const { return localAddr_; }	///返回本端地址
  const InetAddress& peerAddress() const { return peerAddr_; }	///返回对端地址
  bool connected() const { return state_ == kConnected; }	///返回连接状态
  bool disconnected() const { return state_ == kDisconnected; }	///返回连接状态
  // return true if success.
  bool getTcpInfo(struct tcp_info*) const;
  string getTcpInfoString() const;

  ///发送数据
  // void send(string&& message); // C++11
  void send(const void* message, int len);	
  void send(const StringPiece& message);
  // void send(Buffer&& message); // C++11
  void send(Buffer* message);  // this one will swap data
  void shutdown(); // NOT thread safe, no simultaneous calling
  // void shutdownAndForceCloseAfter(double seconds); // NOT thread safe, no simultaneous calling
  void forceClose();	///强制关闭连接
  void forceCloseWithDelay(double seconds);	///延后强制关闭连接
  void setTcpNoDelay(bool on);	///是否开启Nagle算法
  // reading or not
  void startRead();	///更新channel监听读事件
  void stopRead();	///更新channel取消监听读事件
  bool isReading() const { return reading_; }; // NOT thread safe, may race with start/stopReadInLoop 返回是否在监听读事件

  void setContext(const boost::any& context)
  { context_ = context; }

  const boost::any& getContext() const
  { return context_; }

  boost::any* getMutableContext()
  { return &context_; }

  void setConnectionCallback(const ConnectionCallback& cb)	///连接建立成功或者销毁时会执行的回调函数
  { connectionCallback_ = cb; }

  void setMessageCallback(const MessageCallback& cb)	///从连接中读取可用的数据后执行的回调函数
  { messageCallback_ = cb; }

  void setWriteCompleteCallback(const WriteCompleteCallback& cb)	///写操作完成时执行的回调函数
  { writeCompleteCallback_ = cb; }

  ///设置高水位
  void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)
  { highWaterMarkCallback_ = cb; highWaterMark_ = highWaterMark; }

  /// Advanced interface
  Buffer* inputBuffer()	///返回读缓存
  { return &inputBuffer_; }

  Buffer* outputBuffer()	///返回写缓存
  { return &outputBuffer_; }

  /// Internal use only.
  void setCloseCallback(const CloseCallback& cb)
  { closeCallback_ = cb; }

  // 当TcpServer接收新连接时会调用
  void connectEstablished();   // should be called only once
  ///当TcpServer将该对象从connectmap中移除时,会调用该函数
  void connectDestroyed();  // should be called only once

 private:
 ///当前对象状态
  enum StateE { kDisconnected, kConnecting, kConnected, kDisconnecting };
  void handleRead(Timestamp receiveTime);	///读回调
  void handleWrite();	///写回调
  void handleClose();	///关闭回调
  void handleError();	///错误回调
  // void sendInLoop(string&& message);
  ///发送信息
  void sendInLoop(const StringPiece& message);
  void sendInLoop(const void* message, size_t len);
  ///关闭写端
  void shutdownInLoop();
  // void shutdownAndForceCloseInLoop(double seconds);
  ///强制关闭连接
  void forceCloseInLoop();
  ///设置当前对象的状态
  void setState(StateE s) { state_ = s; }
  const char* stateToString() const;
  void startReadInLoop();	///开始监听读事件
  void stopReadInLoop();	///停止监听读事件

  EventLoop* loop_;	///从属的loop
  const string name_;	///连接名称
  StateE state_;  // FIXME: use atomic variable
  bool reading_;	///是否处于监听读事件

  ///针对客户端来说,我们不能暴露这些类
  ///下面我说我fd是,accept()成功时返回的fd,就是建立连接成功时返回的fd
  std::unique_ptr<Socket> socket_;	///将建立连接生成的fd封装成Socket对象
  std::unique_ptr<Channel> channel_;	///通过loop和fd构造一个Channel对象
  const InetAddress localAddr_;	///本端地址
  const InetAddress peerAddr_;	///对端地址
  ConnectionCallback connectionCallback_;	///初次建立连接成功时或者销毁时的会执行的回调函数
  MessageCallback messageCallback_;	///执行完读操作后,将读缓冲区重置
  WriteCompleteCallback writeCompleteCallback_;	///写操作完成之后所执行的回调
  HighWaterMarkCallback highWaterMarkCallback_;	
  CloseCallback closeCallback_;
  size_t highWaterMark_;
  Buffer inputBuffer_;
  Buffer outputBuffer_; // FIXME: use list<Buffer> as output buffer.
  boost::any context_;
  // FIXME: creationTime_, lastReceiveTime_
  //        bytesReceived_, bytesSent_
};

typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;

2.TcpConnection.cc文件

///会在TcpServer初始化时就设置连接回调函数
void muduo::net::defaultConnectionCallback(const TcpConnectionPtr& conn)
{
  LOG_TRACE << conn->localAddress().toIpPort() << " -> "
            << conn->peerAddress().toIpPort() << " is "
            << (conn->connected() ? "UP" : "DOWN");
  // do not call conn->forceClose(), because some users want to register message callback only.
}
///会在Tcp初始化时就设置消息读完之后 操作的回调函数
void muduo::net::defaultMessageCallback(const TcpConnectionPtr&,
                                        Buffer* buf,
                                        Timestamp)
{
  buf->retrieveAll();	///将读缓冲区重置,读索引和写索引回到预置位
}

TcpConnection::TcpConnection(EventLoop* loop,
                             const string& nameArg,
                             int sockfd,
                             const InetAddress& localAddr,
                             const InetAddress& peerAddr)
  : loop_(CHECK_NOTNULL(loop)),	///检查loop不为空
    name_(nameArg),	///连接名字
    state_(kConnecting),	///连接的状态
    reading_(true),	/// 监听读事件
    socket_(new Socket(sockfd)),	///将建立连接成功返回的sockfd进行封装,生成socket_对象
    channel_(new Channel(loop, sockfd)),	///生成一个channel对象
    localAddr_(localAddr),	///本端地址
    peerAddr_(peerAddr),	///对端地址
    highWaterMark_(64*1024*1024)	///高水位标记
{
  ///channel设置读回调,写回调,关闭回调,错误回调
  channel_->setReadCallback(
      std::bind(&TcpConnection::handleRead, this, _1));
  channel_->setWriteCallback(
      std::bind(&TcpConnection::handleWrite, this));
  channel_->setCloseCallback(
      std::bind(&TcpConnection::handleClose, this));
  channel_->setErrorCallback(
      std::bind(&TcpConnection::handleError, this));
  LOG_DEBUG << "TcpConnection::ctor[" <<  name_ << "] at " << this
            << " fd=" << sockfd;
  socket_->setKeepAlive(true);	///开启保活机制 
}

TcpConnection::~TcpConnection()
{
  LOG_DEBUG << "TcpConnection::dtor[" <<  name_ << "] at " << this
            << " fd=" << channel_->fd()
            << " state=" << stateToString();
  assert(state_ == kDisconnected);	///断言连接断开状态
}

bool TcpConnection::getTcpInfo(struct tcp_info* tcpi) const
{
  return socket_->getTcpInfo(tcpi);
}

string TcpConnection::getTcpInfoString() const
{
  char buf[1024];
  buf[0] = '\0';
  socket_->getTcpInfoString(buf, sizeof buf);
  return buf;
}
///发送数据
void TcpConnection::send(const void* data, int len)
{
  send(StringPiece(static_cast<const char*>(data), len));
}

void TcpConnection::send(const StringPiece& message)
{
  if (state_ == kConnected)
  {
    if (loop_->isInLoopThread())
    {
      sendInLoop(message);	///在本线程直接发送数据
    }
    else
    {
      void (TcpConnection::*fp)(const StringPiece& message) = &TcpConnection::sendInLoop;
      ///在loop线程中执行
      loop_->runInLoop(	
          std::bind(fp,
                    this,     // FIXME
                    message.as_string()));
                    //std::forward<string>(message)));
    }
  }
}

// FIXME efficiency!!!
void TcpConnection::send(Buffer* buf)
{
  if (state_ == kConnected)
  {
    if (loop_->isInLoopThread())
    {
      sendInLoop(buf->peek(), buf->readableBytes());	
      buf->retrieveAll();	///将buf缓冲区重置
    }
    else
    {
      void (TcpConnection::*fp)(const StringPiece& message) = &TcpConnection::sendInLoop;
      loop_->runInLoop(
          std::bind(fp,
                    this,     // FIXME
                    buf->retrieveAllAsString()));
                    //std::forward<string>(message)));
    }
  }
}

void TcpConnection::sendInLoop(const StringPiece& message)
{
  sendInLoop(message.data(), message.size());
}

///发送数据最后实际调用的函数
void TcpConnection::sendInLoop(const void* data, size_t len)
{
  loop_->assertInLoopThread();
  ssize_t nwrote = 0;
  size_t remaining = len;
  bool faultError = false;
  if (state_ == kDisconnected)
  {
    LOG_WARN << "disconnected, give up writing";
    return;
  }
  // if no thing in output queue, try writing directly
  if (!channel_->isWriting() && outputBuffer_.readableBytes() == 0)
  {
    nwrote = sockets::write(channel_->fd(), data, len);
    if (nwrote >= 0)
    {
      remaining = len - nwrote;	//剩下未读的字节数量
      if (remaining == 0 && writeCompleteCallback_)
      {
      写完数据后执行的回调任务
        loop_->queueInLoop(std::bind(writeCompleteCallback_, shared_from_this()));
      }
    }
    else // nwrote < 0
    {
      nwrote = 0;
      if (errno != EWOULDBLOCK)	///错误不是本应该被阻塞
      {
        LOG_SYSERR << "TcpConnection::sendInLoop";
        if (errno == EPIPE || errno == ECONNRESET) // FIXME: any others?
        {
          faultError = true;	///默认错误标志置为true
        }	
      }
    }
  }

  assert(remaining <= len);
  if (!faultError && remaining > 0)
  {
    size_t oldLen = outputBuffer_.readableBytes();
    if (oldLen + remaining >= highWaterMark_
        && oldLen < highWaterMark_
        && highWaterMarkCallback_)
    {
      loop_->queueInLoop(std::bind(highWaterMarkCallback_, shared_from_this(), oldLen + remaining));
    }
    outputBuffer_.append(static_cast<const char*>(data)+nwrote, remaining);
    if (!channel_->isWriting())
    {
      channel_->enableWriting();
    }
  }
}

void TcpConnection::shutdown()
{
  // FIXME: use compare and swap
  if (state_ == kConnected)
  {
    setState(kDisconnecting);	///设置正在取消连接状态
    // FIXME: shared_from_this()?
    loop_->runInLoop(std::bind(&TcpConnection::shutdownInLoop, this));	///关闭写端
  }
}

///实际上关闭写端
void TcpConnection::shutdownInLoop()
{
  loop_->assertInLoopThread();
  if (!channel_->isWriting())
  {
    // we are not writing
    socket_->shutdownWrite();
  }
}

void TcpConnection::forceClose()
{
  // FIXME: use compare and swap
  if (state_ == kConnected || state_ == kDisconnecting)
  {
    setState(kDisconnecting);
    loop_->queueInLoop(std::bind(&TcpConnection::forceCloseInLoop, shared_from_this()));
  }
}

void TcpConnection::forceCloseWithDelay(double seconds)
{
  if (state_ == kConnected || state_ == kDisconnecting)
  {
    setState(kDisconnecting);
    loop_->runAfter(
        seconds,
        makeWeakCallback(shared_from_this(),
                         &TcpConnection::forceClose));  // not forceCloseInLoop to avoid race condition
  }
}

void TcpConnection::forceCloseInLoop()
{
  loop_->assertInLoopThread();
  if (state_ == kConnected || state_ == kDisconnecting)
  {
    // as if we received 0 byte in handleRead();
    handleClose();
  }
}

const char* TcpConnection::stateToString() const
{
  switch (state_)
  {
    case kDisconnected:
      return "kDisconnected";
    case kConnecting:
      return "kConnecting";
    case kConnected:
      return "kConnected";
    case kDisconnecting:
      return "kDisconnecting";
    default:
      return "unknown state";
  }
}

void TcpConnection::setTcpNoDelay(bool on)
{
  socket_->setTcpNoDelay(on);	///设置Nagle算法是否开启
}

void TcpConnection::startRead() ///开启监听读事件状态

{
  loop_->runInLoop(std::bind(&TcpConnection::startReadInLoop, this));
}

void TcpConnection::startReadInLoop()	{
  loop_->assertInLoopThread();
  if (!reading_ || !channel_->isReading())
  {
    channel_->enableReading();
    reading_ = true;
  }
}

void TcpConnection::stopRead()	///取消监听都时间状态
{
  loop_->runInLoop(std::bind(&TcpConnection::stopReadInLoop, this));
}

void TcpConnection::stopReadInLoop()
{
  loop_->assertInLoopThread();
  if (reading_ || channel_->isReading())
  {
    channel_->disableReading();
    reading_ = false;
  }
}

void TcpConnection::connectEstablished()	///当新连接被确定时会执行一次
{
  loop_->assertInLoopThread();
  assert(state_ == kConnecting);
  setState(kConnected);
  channel_->tie(shared_from_this());
  channel_->enableReading();

  connectionCallback_(shared_from_this());
}

void TcpConnection::connectDestroyed()	///将该对象从TcpServer中的connectionMap中移除出去
{
  loop_->assertInLoopThread();
  if (state_ == kConnected)
  {
    setState(kDisconnected);
    channel_->disableAll();	///取消监听任何事情

    connectionCallback_(shared_from_this());
  }
  channel_->remove();
}

void TcpConnection::handleRead(Timestamp receiveTime)	///channel执行的读回调
{
  loop_->assertInLoopThread();
  int savedErrno = 0;
  ssize_t n = inputBuffer_.readFd(channel_->fd(), &savedErrno);	///从缓冲区中读取数据
  if (n > 0)
  {
    messageCallback_(shared_from_this(), &inputBuffer_, receiveTime);
  }
  else if (n == 0)
  {
    handleClose();
  }
  else
  {
    errno = savedErrno;
    LOG_SYSERR << "TcpConnection::handleRead";
    handleError();
  }
}

void TcpConnection::handleWrite()	///channel执行的写回调
{
  loop_->assertInLoopThread();
  if (channel_->isWriting())	///判断channel是否处于监听写事件
  {
    ssize_t n = sockets::write(channel_->fd(),
                               outputBuffer_.peek(),
                               outputBuffer_.readableBytes());
    if (n > 0)
    {
      outputBuffer_.retrieve(n);
      if (outputBuffer_.readableBytes() == 0)
      {
        channel_->disableWriting();	///使其不再监听写事件
        if (writeCompleteCallback_)
        {
          loop_->queueInLoop(std::bind(writeCompleteCallback_, shared_from_this()));
        }
        if (state_ == kDisconnecting)
        {
          shutdownInLoop();	///关闭写端
        }
      }
    }
    else
    {
      LOG_SYSERR << "TcpConnection::handleWrite";
      // if (state_ == kDisconnecting)
      // {
      //   shutdownInLoop();
      // }
    }
  }
  else
  {
    LOG_TRACE << "Connection fd = " << channel_->fd()
              << " is down, no more writing";
  }
}

void TcpConnection::handleClose()	///channel执行的关闭回调
{
  loop_->assertInLoopThread();
  LOG_TRACE << "fd = " << channel_->fd() << " state = " << stateToString();
  assert(state_ == kConnected || state_ == kDisconnecting);
  // we don't close fd, leave it to dtor, so we can find leaks easily.
  setState(kDisconnected);
  channel_->disableAll();	///channel不监听任何事件

  TcpConnectionPtr guardThis(shared_from_this());
  connectionCallback_(guardThis);
  // must be the last line
  closeCallback_(guardThis);
}

void TcpConnection::handleError()	///channel执行的错误回调
{
  int err = sockets::getSocketError(channel_->fd());
  LOG_ERROR << "TcpConnection::handleError [" << name_
            << "] - SO_ERROR = " << err << " " << strerror_tl(err);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值