TcpServer类的启动过程

编写一段代码测试TcpServer类的功能

#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>

#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

void onConnection(const TcpConnectionPtr& conn)
{
  if (conn->connected())
  {
    printf("onConnection(): new connection [%s] from %s\n",
           conn->name().c_str(),
           conn->peerAddress().toIpPort().c_str());
  }
  else
  {
    printf("onConnection(): connection [%s] is down\n",
           conn->name().c_str());
  }
}

void onMessage(const TcpConnectionPtr& conn,
               const char* data,
               ssize_t len)
{
  printf("onMessage(): received %zd bytes from connection [%s]\n",
         len, conn->name().c_str());
}

int main()
{
  printf("main(): pid = %d\n", getpid());

  InetAddress listenAddr(8888);
  EventLoop loop;

  TcpServer server(&loop, listenAddr, "TestServer");
  server.setConnectionCallback(onConnection);
  server.setMessageCallback(onMessage);
  server.start();

  loop.loop();
}

1.构造一个TcpServer

  TcpServer server(&loop, listenAddr, "TestServer");

TcpServer的构造函数作用如下:
①.构造一个TcpServer::acceptor_,用于在该服务器上关注侦听套接字是否可读,TcpServer::acceptor_的具体构造过程如下:创建监听套接字Acceptor::acceptSocket_,创建Acceptor::acceptChannel_负责Acceptor::acceptSocket_的I/O事件分发,将Acceptor::handleRead()注册给Channel_::readCallback_,使在Acceptor::acceptSocket_可读时调用Acceptor::handleRead()。
②.将net::defaultConnectionCallback()(此函数定义在Callbacks.h中)注册给TcpServer::connectionCallback_(),将net::defaultMessageCallback()注册给TcpServer::messageCallback_()。
③.调用setNewConnectionCallback(const NewConnectionCallback& cb)将TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)注册给刚刚构造的TcpServer::acceptor_中的Acceptor::newConnectionCallback_(int sockfd, const InetAddress& peerAddr)。
TcpServer构造完成后,若Acceptor::acceptSocket_有事件可读,则函数的调用流程如下:
Channel::handleEvent(Timestamp receiveTime)>>Channel_::readCallback_(Timestamp receiveTime)>>Acceptor::handleRead()>>Acceptor::newConnectionCallback_(int sockfd, const InetAddress& peerAddr)>>TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)

2.注册回调函数

  server.setConnectionCallback(onConnection);
  server.setMessageCallback(onMessage);

将onConnection()注册给连接建立时的回调函数TcpServer::connectionCallback_()。
将onMessage()注册给消息到达时的回调函数TcpServer::messageCallback_()。

3.启动服务器TcpServer

server.start();
void TcpServer::start()
{
  if (!started_)
  {
    started_ = true;
	threadPool_->start(threadInitCallback_);
  }

  if (!acceptor_->listenning())
  {
	// get_pointer返回原生指针
    loop_->runInLoop(
        boost::bind(&Acceptor::listen, get_pointer(acceptor_)));
  }
}

TcpServer::start()调用Acceptor::listen()成员函数执行Socket::listen(),之后调用Channel::enableReading()设置通道Acceptor::acceptChannel_关注Acceptor::acceptSocket_可读事件,并调用Channel::update()维护和更新poller中的文件描述符列表PollPoller::pollfds_,用于注册或者更新通道所关注的事件。
函数调用过程如下:
TcpServer::start()
.>>EventLoop::runInLoop(const Functor& cb)>>Acceptor::listen()>>Socket::listen()
.>>Channel::enableReading()>>Channel::update()>>EventLoop::updateChannel(Channel* channel)>>PollPoller::updateChannel(Channel* channel)

4.运行事件循环函数EventLoop::loop()

loop.loop();
void EventLoop::loop()
{
  assert(!looping_);
  // 断言当前处于创建该对象的线程中
  assertInLoopThread();
  looping_ = true;
  quit_ = false;
  LOG_TRACE << "EventLoop " << this << " start looping";

  //::poll(NULL, 0, 5*1000);
  while (!quit_)
  {

	//清空vector<Channel*>即ChannelList的成员
    activeChannels_.clear();
	//调用poll()获得当前活动事件的channel列表activeChannels,并返回当前时间
    pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);
    //++iteration_;
    if (Logger::logLevel() <= Logger::TRACE)
    {
      printActiveChannels();
    }
    // TODO sort channel by priority
    eventHandling_ = true;
	//依次调用activeChannels_中每个channel的handleEvent()函数
    for (ChannelList::iterator it = activeChannels_.begin();
        it != activeChannels_.end(); ++it)
    {
      currentActiveChannel_ = *it;
      currentActiveChannel_->handleEvent(pollReturnTime_);
    }
    currentActiveChannel_ = NULL;
    eventHandling_ = false;
	//调用pendingFunctors_里面的所有函数
    doPendingFunctors();
  }

  LOG_TRACE << "EventLoop " << this << " stop looping";
  looping_ = false;
}

此函数的功能如下:
①.EventLoop::loop()调用PollPoller::poll(int timeoutMs, ChannelList* activeChannels),之后调用::poll(&pollfds_.begin(), pollfds_.size(), timeoutMs),获得在TcpServer::start()中由PollPoller::updateChannel(Channel* channel)更新后pollfds_中的pollfd::revents_不为空的Channel,再调用PollPoller::fillActiveChannels(int numEvents,ChannelList* activeChannels)填充活动通道的列表EventLoop::activeChannels,并返回当前时间。
②.在得到EventLoop::activeChannels后,依次调用EventLoop::activeChannels中每个Channel的Channel::handleEvent(Timestamp receiveTime),处理Channel的事件,Channel::handleEvent(Timestamp receiveTime)调用Channel_::readCallback_(receiveTime),而此前将Acceptor::handleRead()注册给了Channel_::readCallback_(receiveTime),因此回调Acceptor::handleRead(),之后调用Acceptor::newConnectionCallback_(int sockfd, const InetAddress& peerAddr),即TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)。
③.TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)为监听套接字acceptSocket_可读时调用的表示新连接建立的函数,该函数建立一个新的TcpConnection对象,即TcpConnection::conn,TcpConnection::conn构造过程如下:
用文件描述符sockfd构造一个用于IO事件的套接字TcpConnection::socket_,同时构造一个负责TcpConnection::socket_上IO事件的TcpConnection::channel_,之后注册TcpConnection::channel_里面的各个回调函数,调用Channel_::setReadCallback(const ReadEventCallback& cb)将TcpConnection::handleRead(Timestamp receiveTime)注册给通道可读事件到来的时候的回调函数Channel_::readCallback_(),调用Channel_::setWriteCallback(const EventCallback& cb)将TcpConnection::handleWrite()注册给通道可写事件到来的时候的回调函数Channel_::writeCallback_(),调用Channel_::setCloseCallback(const EventCallback& cb)将TcpConnection::handleClose()注册给连接关闭的时候的回调函数Channel_:closeCallback_ (),调用Channel_::setErrorCallback(const EventCallback& cb)将TcpConnection::handleError()注册给发生错误的时候的回调函数Channel_::errorCallback_()。
④.TcpConnection::conn构造完成后,调用TcpConnection::setConnectionCallback(const ConnectionCallback& cb)将TcpServer::connectionCallback_()注册给连接到来时的回调函数TcpConnection::connectionCallback_(),调用TcpConnection::setMessageCallback(const MessageCallback& cb)将TcpServer::messageCallback_()注册给连接到来时的回调函数TcpConnection::messageCallback_(),调用TcpConnection::setWriteCompleteCallback(const WriteCompleteCallback& cb)将TcpServer::writeCompleteCallback_()注册给连接到来时的回调函数TcpConnection::writeCompleteCallback_(),调用TcpConnection::setCloseCallback(const CloseCallback& cb)将TcpServer::removeConnection(const TcpConnectionPtr& conn)注册给连接到来时的回调函数TcpConnection::closeCallback_()。注册完各个回调函数后,通过EventLoop::runInLoop(const Functor& cb)调用TcpConnection::connectEstablished(),调用Channel::enableReading()使Channel::channel_关注TcpConnection::socket_可读事件,并调用Channel::update()维护和更新poller中的文件描述符列表PollPoller::pollfds_,用于注册或者更新Channel::channel_所关注的事件。最后调用TcpConnection::connectionCallback_(),即TcpServer::connectionCallback_(),该函数被onConnection(const TcpConnectionPtr& conn)注册,至此,连接已完成。
⑤.最后,调用EventLoop::doPendingFunctors()把EventLoop::pendingFunctors_里的函数都执行掉。
⑥.由于while (!quit_)仍然成立,继续循环,第二次循环开始时,调用vector::clear()清空当前的活跃通道列表EventLoop::activeChannels_,之后重复①,此时不仅需要关注新连接建立的事件,还需要关注已经建立的连接上的IO事件。

函数调用过程如下:
EventLoop::loop()
.>>PollPoller::poll(int timeoutMs, ChannelList* activeChannels)>>::poll(&pollfds_.begin(), pollfds_.size(), timeoutMs)>>PollPoller::fillActiveChannels(int numEvents,ChannelList* activeChannels)
.>>Channel::handleEvent(Timestamp receiveTime)>>Channel_::readCallback_(receiveTime)>>Acceptor::handleRead()>>Acceptor::newConnectionCallback_(int sockfd, const InetAddress& peerAddr)>>TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)>>TcpConnection::TcpConnection(EventLoop* loop,const string& nameArg, int sockfd, const InetAddress& localAddr, const InetAddress& peerAddr)>>Channel_::setReadCallback(const ReadEventCallback& cb)>>Channel_::setWriteCallback(const EventCallback& cb)>>Channel_::setCloseCallback(const EventCallback& cb)>>Channel_::setErrorCallback(const EventCallback& cb)>>TcpConnection::setConnectionCallback(const ConnectionCallback& cb)>>TcpConnection::setMessageCallback(const MessageCallback& cb)>>TcpConnection::setWriteCompleteCallback(const WriteCompleteCallback& cb)>>TcpConnection::setCloseCallback(const CloseCallback& cb)>>EventLoop::runInLoop(const Functor& cb)>>TcpConnection::connectEstablished()>>Channel::enableReading()>>Channel::update()>>EventLoop::updateChannel(Channel* channel)>>PollPoller::updateChannel(Channel* channel)>>TcpConnection::connectionCallback_()>>TcpServer::connectionCallback_()>>onConnection(const TcpConnectionPtr& conn)
.>>EventLoop::doPendingFunctors()
.>>第二次循环开始,假设有一条消息到来
.>>vector::clear()
.>>PollPoller::poll(int timeoutMs, ChannelList* activeChannels)>>::poll(&pollfds_.begin(), pollfds_.size(), timeoutMs)>>PollPoller::fillActiveChannels(int numEvents,ChannelList* activeChannels)
.>>Channel::handleEvent(Timestamp receiveTime)>>Channel_::readCallback_(receiveTime)>>TcpConnection::handleRead(Timestamp receiveTime)>>TcpConnection::messageCallback_()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值