编写一小段代码测试Acceptor类的功能
#include <muduo/net/Acceptor.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/InetAddress.h>
#include <muduo/net/SocketsOps.h>
#include <stdio.h>
using namespace muduo;
using namespace muduo::net;
void newConnection(int sockfd, const InetAddress& peerAddr)
{
printf("newConnection(): accepted a new connection from %s\n",
peerAddr.toIpPort().c_str());
::write(sockfd, "How are you?\n", 13);
sockets::close(sockfd);
}
int main()
{
printf("main(): pid = %d\n", getpid());
InetAddress listenAddr(8888);
EventLoop loop;
Acceptor acceptor(&loop, listenAddr);
acceptor.setNewConnectionCallback(newConnection);
acceptor.listen();
loop.loop();
}
1.构造一个Acceptor
Acceptor acceptor(&loop, listenAddr)
构造函数创建监听套接字Acceptor::acceptSocket_,创建Channel_::acceptChannel_负责Acceptor::acceptSocket_的I/O事件分发,将Acceptor::handleRead()注册给Channel_::readCallback_,使在Acceptor::acceptSocket_可读时调用Acceptor::handleRead()。
2.注册连接建立时的回调函数
acceptor.setNewConnectionCallback(newConnection)
注册连接建立时的回调函数Acceptor::newConnectionCallback_=newConnection
3.Acceptor::listen()函数的调用过程
acceptor.listen();
void Acceptor::listen()
{
loop_->assertInLoopThread();
listenning_ = true;
acceptSocket_.listen();
acceptChannel_.enableReading();
}
Acceptor::listen()成员函数执行Socket::listen(),之后调用Channel::enableReading()设置通道Channel关注Acceptor::acceptSocket_可读事件,并调用Channel::update()维护和更新poller中的文件描述符列表PollPoller::pollfds_,用于注册或者更新通道所关注的事件。
函数调用过程如下:
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),获得由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),即newConnection(int sockfd, const InetAddress& peerAddr)。
最后,调用EventLoop::doPendingFunctors()把EventLoop::pendingFunctors_里的函数都执行掉。
函数调用过程如下:
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)>>newConnection(int sockfd, const InetAddress& peerAddr)
.>>EventLoop::doPendingFunctors()