TcpServer类解析——muduo源码分析

该Evenloop运行在主线程,仅用于监听客户端的建立连接请求,不负责监听TcpConnection的fd。该EventloopThread不从EventloopThreadPool中取。TcpServer中有一个线程池,大小固定不支持动态扩容。TcpServer直接供用户使用。

#ifndef MUDUO_NET_TCPSERVER_H
#define MUDUO_NET_TCPSERVER_H

#include "muduo/base/Atomic.h"
#include "muduo/base/Types.h"
#include "muduo/net/TcpConnection.h"

#include <map>

namespace muduo
{
namespace net
{

class Acceptor;
class EventLoop;
class EventLoopThreadPool;

class TcpServer : noncopyable
{
 public:
  typedef std::function<void(EventLoop*)> ThreadInitCallback;
  enum Option
  {
    kNoReusePort,
    kReusePort,
  };

  //传入TcpServer所属的loop,本地ip,服务器名
  TcpServer(EventLoop* loop,
            const InetAddress& listenAddr,
            const string& nameArg,
            Option option = kNoReusePort);
  ~TcpServer();  
  //返回一些对象
  const string& ipPort() const { return ipPort_; }
  const string& name() const { return name_; }
  EventLoop* getLoop() const { return loop_; }


  //设置线程池中线程的数量
  void setThreadNum(int numThreads);
  //线程初始化后回调
  void setThreadInitCallback(const ThreadInitCallback& cb)
  { threadInitCallback_ = cb; }
  // valid after calling start()
  std::shared_ptr<EventLoopThreadPool> threadPool()
  { return threadPool_; }
  //启动线程池管理器,将Acceptor::listen()加入调度队列
  void start();
  //如果有新的客户端连接建立或者请求关闭连接,则调用->connectionCallback_。会在新建一个TcpConnection时传给后者,供TcpConnection使用。
  void setConnectionCallback(const ConnectionCallback& cb)
  { connectionCallback_ = cb; }

  //如果有消息到达时调用->MessageCallback。会在新建一个TcpConnection时传给后者,供TcpConnection使用。
  void setMessageCallback(const MessageCallback& cb)
  { messageCallback_ = cb; }

  //消息成功写入tcp内核缓冲区后调用->writeCompleteCallback。会在新建一个TcpConnection时传给后者,供TcpConnection使用。
  void setWriteCompleteCallback(const WriteCompleteCallback& cb)
  { writeCompleteCallback_ = cb; }

 private:
  //传给Acceptor,Acceptor会在有新的连接到来时调用->handleRead()。
  void newConnection(int sockfd, const InetAddress& peerAddr);
  //移除连接。
  void removeConnection(const TcpConnectionPtr& conn);
  //将连接从loop中取出
  void removeConnectionInLoop(const TcpConnectionPtr& conn);
  //string为TcpConnection名,用于找到某个连接。
  typedef std::map<string, TcpConnectionPtr> ConnectionMap;
 
  EventLoop* loop_;  // the acceptor loop
  const string ipPort_;
  const string name_;
  //仅由TcpServer持有
  std::unique_ptr<Acceptor> acceptor_; 
  std::shared_ptr<EventLoopThreadPool> threadPool_;
  ConnectionCallback connectionCallback_;
  MessageCallback messageCallback_;
  WriteCompleteCallback writeCompleteCallback_;
  ThreadInitCallback threadInitCallback_;
  AtomicInt32 started_;
  // always in loop thread
  int nextConnId_;
  ConnectionMap connections_;
};

}  // namespace net
}  // namespace muduo

#endif  // MUDUO_NET_TCPSERVER_H
#include "muduo/net/TcpServer.h"

#include "muduo/base/Logging.h"
#include "muduo/net/Acceptor.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThreadPool.h"
#include "muduo/net/SocketsOps.h"

#include <stdio.h>  // snprintf

using namespace muduo;
using namespace muduo::net;
//第三个参数为TcpServer的名称,用于记录服务器名
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)),
    threadPool_(new EventLoopThreadPool(loop, name_)),
    connectionCallback_(defaultConnectionCallback),//传给TcpConnection
    messageCallback_(defaultMessageCallback),//传给TcpConnection
    nextConnId_(1)
{
//回调ConnectionCallback->newConnection
  acceptor_->setNewConnectionCallback(
      std::bind(&TcpServer::newConnection, this, _1, _2));
}

TcpServer::~TcpServer()
{
  loop_->assertInLoopThread();
  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));
  }
}
//初始化EventLoopThreadPool中的线程数量
void TcpServer::setThreadNum(int numThreads)
{
  assert(0 <= numThreads);
  threadPool_->setThreadNum(numThreads);
}
//启用线程池,然后runInLoop()启用Acceptor::listen()监听
void TcpServer::start()
{
先get然后得到结果是0,然后赋值为1,以后都为1就不会进入if语句  
  if (started_.getAndSet(1) == 0)
  {
  //启动线程池,threadInitCallback_创建好所有线程后调用的回调函数
    threadPool_->start(threadInitCallback_);
    
    assert(!acceptor_->listening());
    loop_->runInLoop(
    //get_pointer()返回一个acceptor原生指针
        std::bind(&Acceptor::listen, get_pointer(acceptor_)));
  }
}
//创建一个新的TcpConnection,然后传入一些参数并给该TcpConnection命名
void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
  loop_->assertInLoopThread();
  EventLoop* ioLoop = threadPool_->getNextLoop();
  char buf[64];
  snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
  ++nextConnId_;
  //给TcpConnection取名
  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
  //传入该TcpConnection所属的EventLoop、TcoConnection的名称、收到的Socetfd、两端的Ip
  //最后以TcpConnection的指针的形式保存
  TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                          connName,
                                          sockfd,
                                          localAddr,
                                          peerAddr));
  connections_[connName] = conn;
  //将前面提到的三个回调函数注册到TcpConnection中
  conn->setConnectionCallback(connectionCallback_);
  conn->setMessageCallback(messageCallback_);
  conn->setWriteCompleteCallback(writeCompleteCallback_);
  //关闭连接时会传入TcpServer的指针,用于删除map中的TcpConnection
  //会调用Channel的CloseCallback(),进而调用TcpConnection的handleClose
  //进而调用removeConnection
    conn->setCloseCallback(
      std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
      //让runInLoop在TcpConnection所在的线程去调用
  ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
}

void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
  // FIXME: unsafe
  loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}
//关闭连接,把fd从map中中移除,在io线程中执行queueInLoop调用connectDestroyed
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));
}

析构函数里的这部分代码怎么理解?

TcpServer::~TcpServer()
{
  loop_->assertInLoopThread();
  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));
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值