4.muduo之TcpServer类

介绍:可以直接当成一个服务器了,你只需要设置loop,绑定地址,服务器名称,SO_REUSEPORT是否开启就行了。如果想要运用多个I/O线程池,在start()函数之前调用setThreadNum(int numThreads)设置线程池中的线程数就可以了.

1.TcpServer.h文件

///
///该类即支持单线程也支持多线程
///该类是一个接口类,所以不暴露太多细节
class TcpServer : noncopyable
{
 public:
 ///线程初始化函数,并不一定需要
  typedef std::function<void(EventLoop*)> ThreadInitCallback;
  enum Option
  {
    kNoReusePort,
    kReusePort,
  };

  //TcpServer(EventLoop* loop, const InetAddress& listenAddr);
  
  TcpServer(EventLoop* loop,
            const InetAddress& listenAddr,
            const string& nameArg,
            Option option = kNoReusePort);
  ~TcpServer();  // force out-line dtor, for std::unique_ptr members.

  const string& ipPort() const { return ipPort_; }
  const string& name() const { return name_; }
  EventLoop* getLoop() const { return loop_; }

  ///设置I/O线程池中线程的数量,一定在start函数前调用
  ///这些线程总是接收新的连接
  ///参数为0时:没有I/O线程被建立,参数为0时默认值
  ///参数为N时:有多个线程,新的连接被 基于轮转法的I/O线程池分配。
  void setThreadNum(int numThreads);	
  ///设置线程初始化函数
  void setThreadInitCallback(const ThreadInitCallback& cb)
  { threadInitCallback_ = cb; }
  /// valid after calling start()
  std::shared_ptr<EventLoopThreadPool> threadPool()
  { return threadPool_; }

  ///如果处于监听状态就启动服务器
  /// 该函数可以被调用多次
  /// 线程安全的函数
  void start();

  /// 设置建立连接成功后的回调
  /// 不是线程安全的
  void setConnectionCallback(const ConnectionCallback& cb)
  { connectionCallback_ = cb; }

  /// 设置消息回调
  /// 不是线程安全的
  void setMessageCallback(const MessageCallback& cb)
  { messageCallback_ = cb; }

  ///设置写回调
  /// 不是线程安全的
  void setWriteCompleteCallback(const WriteCompleteCallback& cb)
  { writeCompleteCallback_ = cb; }

 private:
  /// acceptor设置的回调
  void newConnection(int sockfd, const InetAddress& peerAddr);
  /// Thread safe.
  void removeConnection(const TcpConnectionPtr& conn);	///移除已建立的连接
  /// Not thread safe, but in loop
  void removeConnectionInLoop(const TcpConnectionPtr& conn);	///实际上的移除连接的操作

  typedef std::map<string, TcpConnectionPtr> ConnectionMap;	///已建立的连接map

  EventLoop* loop_;  // the acceptor loop
  const string ipPort_;	//本地地址
  const string name_;	//服务名字
  std::unique_ptr<Acceptor> acceptor_; //起到监听作用的对象accept()
  std::shared_ptr<EventLoopThreadPool> threadPool_;	///I/O线程池
  ConnectionCallback connectionCallback_;	///内部就是输出本地的地址,对端的地址,连接状态
  MessageCallback messageCallback_;
  WriteCompleteCallback writeCompleteCallback_;
  ThreadInitCallback threadInitCallback_;	///线程初始化函数
  AtomicInt32 started_;
  // always in loop thread
  int nextConnId_;
  ConnectionMap connections_;
};

2.TcpServer.cc文件

TcpServer::TcpServer(EventLoop* loop,
                     const InetAddress& listenAddr,
                     const string& nameArg,
                     Option option)
  : loop_(CHECK_NOTNULL(loop)),	///检查不为空
    ipPort_(listenAddr.toIpPort()),	///绑定的地址
    name_(nameArg),	///服务名称
    acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),///构造一个Acceptor对象
    threadPool_(new EventLoopThreadPool(loop, name_)),	///构造一个I/O线程池对象
    connectionCallback_(defaultConnectionCallback),	///该回调函数输出本地地址,对端地址,连接状态
    messageCallback_(defaultMessageCallback),	///将buffer中的读索引和写索引重置
    nextConnId_(1)	///下一个建立的连接ID位1
{
  acceptor_->setNewConnectionCallback(
      std::bind(&TcpServer::newConnection, this, _1, _2));	///设置建立连接的回调函数
}

TcpServer::~TcpServer()
{
  loop_->assertInLoopThread();	//断言是否在loop线程
  LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";

  for (auto& item : connections_)
  {
    TcpConnectionPtr conn(item.second);
    item.second.reset();
    conn->getLoop()->runInLoop(
      std::bind(&TcpConnection::connectDestroyed, conn));
  }
}
///设置I/O线程池中的线程数量
void TcpServer::setThreadNum(int numThreads)
{
  assert(0 <= numThreads);
  threadPool_->setThreadNum(numThreads);
}

//开启服务器
void TcpServer::start()
{
  if (started_.getAndSet(1) == 0)
  {
    threadPool_->start(threadInitCallback_);	///I/O线程池开始工作

    assert(!acceptor_->listening());
    loop_->runInLoop(
        std::bind(&Acceptor::listen, get_pointer(acceptor_)));	///acceptor_启动监听任务
  }
}

///建立新连接
void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
  loop_->assertInLoopThread();	///断言是否在loop线程
  EventLoop* ioLoop = threadPool_->getNextLoop();	///内部采用轮转法,决定将要选择的I/O线程
  char buf[64];
  snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
  ++nextConnId_;	///下一个连接的id
  string connName = name_ + buf;	///新连接的名称

  LOG_INFO << "TcpServer::newConnection [" << name_
           << "] - new connection [" << connName
           << "] from " << peerAddr.toIpPort();
  InetAddress localAddr(sockets::getLocalAddr(sockfd));	///本地地址
  // FIXME poll with zero timeout to double confirm the new connection
  // FIXME use make_shared if necessary
  TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                          connName,
                                          sockfd,
                                          localAddr,
                                          peerAddr));	///建立新连接
  connections_[connName] = conn;
  conn->setConnectionCallback(connectionCallback_);	///输出本地地址,对端地址,连接状态
  conn->setMessageCallback(messageCallback_);	///将buffer的读索引和写索引重置
  conn->setWriteCompleteCallback(writeCompleteCallback_);	///写完成后调用的回调
  ///销毁链接
  conn->setCloseCallback(
      std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe 
  ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));	///开启监听读事件
}

void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
  // FIXME: unsafe 在主loop线程中执行
  loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}

void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
  loop_->assertInLoopThread();
  LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_
           << "] - connection " << conn->name();
  size_t n = connections_.erase(conn->name());
  (void)n;
  assert(n == 1);
  EventLoop* ioLoop = conn->getLoop();
  ioLoop->queueInLoop(
      std::bind(&TcpConnection::connectDestroyed, conn));
}


猜你喜欢

转载自blog.csdn.net/qq_42987442/article/details/108474014