muduo的Tcpserver类源码分析

 

TcpServer是创建一个服务器的开始。

TcpServer class的功能是管理accept(2)获得的TcpConnection。TcpServer是供用户直接使用的,生命期由用户控制

TcpServer新建连接的相关函数调用顺序如图下所示:

muduo的Tcpserver类源码分析

其中Channel::handleEvent()的触发条件是listening socket可读,表明有新连接到达。TcpServer会为新连接创建对应的TcpConnection对象。

TcpServer class的接口和属性如下图所示:

muduo的Tcpserver类源码分析

主要讲下TcpServer主要的几个函数

首先讲下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),
    messageCallback_(defaultMessageCallback),
    nextConnId_(1)
{
  acceptor_->setNewConnectionCallback(
      std::bind(&TcpServer::newConnection, this, _1, _2));
}

最重要的是  acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),服务器首先需要一个监听套接字来监听是否有新的连接加入,而Acceptor负责监听套接字的创建和端口绑定。

void start(){
      threadPool_->start(threadInitCallback_);   //启动线程池管理器
    loop_->runInLoop(
        std::bind(&Acceptor::listen, get_pointer(acceptor_))); //把Acceptor::listen()加入调度队列或立即调用

};  

 

//处理监听套接字接收到的新的连接请求

//此函数被注册到Acceptor::newConnectionCallback(在TcpServer的构造函数中注册),之后被Acceptor::handleRead()中accept()新连接后调用

void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr);

{

EventLoop* ioLoop=threadPool_->getNextLoop();     //线程池中取一个线程分配给新建连接 RR方式

TcpConnectionPtr conn(new TcpConnection(ioLoop,
                                          connName,
                                          sockfd,
                                          localAddr,
                                          peerAddr));     // 创建一个TcpConnextion对象,表示每一个已连接

  connections_[connName] = conn;

conn->setConnectionCallback(connectionCallback_);        //   connectionCallback_,messageCallback_,writeCompleteCallback_需要用户来提供,应该会注册到TcpConnection中的Channel对象的中

conn->setMessageCallback(messageCallback_);
  conn->setWriteCompleteCallback(writeCompleteCallback_);
  conn->setCloseCallback(
      std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
  ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));

}

 

我的理解是首先创建一个EventLoop(有点儿主线程的意思,),创建一个TcpServer来管理监听的套接字和连接套接字的信息,Acceptor class负责监听套接字,这是一个内部类,对外是隐藏的。当poll被监听套接字**时,调用AcceptChannel中的handleEvent(),在handleEvent()中从线程池中取得一个线程(采用RR的方法),并且new一个TcpConnection对象,TcpConnection负责管理连接套接字,每一个连接套接字有一个TcpConnection相对应,这个线程负责处理该已连接套接字。