本文共 2456 字,大约阅读时间需要 8 分钟。
EventLoop : 事件循环器,底层通过IO复用实现,用于监听所有的文件描述符Acceptor:用于接收一个新的连接,Channel : 用于事件的分发(当检测到有事件发生的时候,事件循环器通知相应的Channel,由Channel 进行事件的分发,一个文件描述符对应一个Channel。所以,Channel 分发的是对应文件描述符上到达的事件)
这里罗列几个关键的函数
TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr, const string& nameArg, Option option) : loop_(CHECK_NOTNULL(loop)), //获取端口 ipPort_(listenAddr.toIpPort()), name_(nameArg), //创建一个acceptor对象 用于操作新的连接 acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)), //创建一个线程池 threadPool_(new EventLoopThreadPool(loop, name_)), //connectionCallback_ 指向默认的链接回调函数 //在Tcpserver 中调用 connectionCallback_ 相当于调用 defaultConnectionCallback connectionCallback_(defaultConnectionCallback), messageCallback_(defaultMessageCallback), nextConnId_(1){ /* 在Acceptor 中 void setNewConnectionCallback(const NewConnectionCallback& cb) { newConnectionCallback_ = cb; } */ //accept 获取一个新的连接的时候直接调用 tcpserver 的newConnection acceptor_->setNewConnectionCallback( std::bind(&TcpServer::newConnection, this, _1, _2));}
void TcpServer::setThreadNum(int numThreads){ assert(0 <= numThreads); threadPool_->setThreadNum(numThreads);}
void TcpServer::start(){ if (started_.getAndSet(1) == 0) { //开启线程池 threadPool_->start(threadInitCallback_); assert(!acceptor_->listenning()); //开始监听 loop_->runInLoop( std::bind(&Acceptor::listen, get_pointer(acceptor_))); }}
Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport) : loop_(loop), acceptSocket_(sockets::createNonblockingOrDie(listenAddr.family())), //构造Channel对象,该Channel对象服务器的接收连接的文件描述符上的事件。 acceptChannel_(loop, acceptSocket_.fd()), listenning_(false), idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC)){ assert(idleFd_ >= 0); acceptSocket_.setReuseAddr(true); acceptSocket_.setReusePort(reuseport); acceptSocket_.bindAddress(listenAddr); //当有读事件发生的时候,调用handleRead函数 acceptChannel_.setReadCallback( //Channel对象注册回调函数,处理读事件 std::bind(&Acceptor::handleRead, this));}
void Acceptor::listen(){ loop_->assertInLoopThread(); //监听状态改为Ture listenning_ = true; //开始监听 acceptSocket_.listen(); //检测该文件描述符上的读事件,将Channel 对象放入事件循环器中,此时EventLoop 开始监听acceptChannel_中的文件描述符 acceptChannel_.enableReading();}
转载地址:http://danwi.baihongyu.com/