Muduo源码刨析-完成服务器功能的TcpServer类

目录

  • TcpServer类
    • 功能
    • 数据成员
    • 暴露的接口

TcpServer类

功能

  TcpServer是muduo库中创建Tcp服务器的类,可以通过对:TcpServermsgcallback 进行设置,可以完成我们想要的服务器功能,例如实现一个echo服务器,实现一个web服务器.

数据成员

		EventLoop *m_loop;///Main Creator(也就是acceptor)运行的loop,若threadNUm为0,那么说有的事务处理都在这个loop上
     	const string m_ipPort;///监听端口
        const string m_name;///server名
        std::unique_ptr<Acceptor> m_acceptor; // 连接接收器
        std::shared_ptr<EventLoopThreadPool> m_eventLoopThreadPool; //该服务器的线程池,(默认没有)
        ConnectionCallBack m_connectionCb;///连接上会发生的回调
        MessageCallBack m_msgCb;///最重要的回调,业务代码在此实现
        ConnectionCallBack m_sendFinishCb;///完成后的回调
        ThreadInitCb m_threadInitCb;
        std::atomic<int32_t> m_started;
        int m_nextConnId;
        ConnectionMap m_connections;///通过TcpConnection的名字管理TcpConnection
		

暴露的接口

  		void setThreadNum(int threadNum);

        void setThreadInitCallBack(const ThreadInitCb &cb) {
            m_threadInitCb = cb;
        }

        std::shared_ptr<EventLoopThreadPool> threadPool() { return m_eventLoopThreadPool; }

        void start();
		
        void setConnectionCallback(const ConnectionCallBack &cb) { m_connectionCb = cb; }

        /// Set message callback.
        /// Not thread safe.
        ///最为重要的接口
        void setMessageCallback(const MessageCallBack &cb) { m_msgCb = cb; }

        /// Set write complete callback.
        /// Not thread safe.
        void setWriteCompleteCallback(const ConnectionCallBack &cb) { m_sendFinishCb = cb; 
    }
TcpServer::TcpServer(EventLoop *loop, const InetAddress &addr, const string &nameArg, TcpServer::Option opt)
        : m_loop(loop), m_acceptor(new Acceptor(m_loop, addr, opt == KReusePort)),
          m_eventLoopThreadPool(new EventLoopThreadPool(loop, nameArg)), m_ipPort(addr.toIpPort()),
          m_connectionCb(defaultConnectionCallBcak), m_msgCb(defaultMessageCallback), m_nextConnId(1), m_started(0) {
    m_acceptor->setNewConnectionCallBack(
            std::bind(&TcpServer::newConnection, this, std::placeholders::_1, std::placeholders::_2));///关键点,将acceptor的newconnectioncb设置成自己的
}

其中newConnection的主要作用就是将该服务器处理的所有tcpconnection的三个回调转换成该服务器执行的操作代码如下

void CzyNetFrame::TcpServer::newConnection(int sockfd, const CzyNetFrame::InetAddress &peerAddr) {
    m_loop->assertInLoopThread();
    EventLoop *ioLoop = m_eventLoopThreadPool->getNextLoop();
    char buf[64];
    snprintf(buf, sizeof buf, "-%s#%d", m_ipPort.c_str(), m_nextConnId);
    ++m_nextConnId;
    string connName = m_name + buf;

    LOG_INFO << "TcpServer::newConnection [" << m_name
             << "] - new connection [" << connName
             << "] from " << peerAddr.toIpPort();
    InetAddress localAddr(sockets::getLocalAddr(sockfd));
    TcpConnectionPtr conn(new TcpConnection(ioLoop, connName,
                                            sockfd,
                                            localAddr,
                                            peerAddr));
    m_connections[connName] = conn;
    conn->setConnectionCb(m_connectionCb);
    conn->setMessageCb(m_msgCb);
    conn->setWriteFinishCb(m_sendFinishCb);
    conn->setCloseCb(
            std::bind(&TcpServer::removeConnection, this, std::placeholders::_1)); // FIXME: unsafe
    ioLoop->runInLoop(std::bind(&TcpConnection::connectionEstablished, conn));

}

在设置妥当后,会调用start来激活acceptor的listen,后者在接收到新连接后会转过头来调用newConnection建立连接,设置回调,这个start是手动调用的,并且:start将创建一个eventloop的threadpool,后者使用环的调度算法来完成一定意义上的负载均衡,代码如下:

void TcpServer::start() {
    if (atomic_fetch_add(&m_started, 1) == 0) {
        m_eventLoopThreadPool->start(m_threadInitCb);
        assert(!m_acceptor->isListening());
        m_loop->runInLoop(std::bind(&Acceptor::listen, m_acceptor.get()));
    }
}

你可能感兴趣的:(服务器,网络)