TcpServer是muduo库中创建Tcp服务器的类,可以通过对:TcpServer的msgcallback 进行设置,可以完成我们想要的服务器功能,例如实现一个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()));
}
}