该Evenloop运行在主线程,仅用于监听客户端的建立连接请求,不负责监听TcpConnection的fd。该EventloopThread不从EventloopThreadPool中取。TcpServer中有一个线程池,大小固定不支持动态扩容。TcpServer直接供用户使用。
#ifndef MUDUO_NET_TCPSERVER_H
#define MUDUO_NET_TCPSERVER_H
#include "muduo/base/Atomic.h"
#include "muduo/base/Types.h"
#include "muduo/net/TcpConnection.h"
#include <map>
namespace muduo
{
namespace net
{
class Acceptor;
class EventLoop;
class EventLoopThreadPool;
class TcpServer : noncopyable
{
public:
typedef std::function<void(EventLoop*)> ThreadInitCallback;
enum Option
{
kNoReusePort,
kReusePort,
};
//传入TcpServer所属的loop,本地ip,服务器名
TcpServer(EventLoop* loop,
const InetAddress& listenAddr,
const string& nameArg,
Option option = kNoReusePort);
~TcpServer();
//返回一些对象
const string& ipPort() const { return ipPort_; }
const string& name() const { return name_; }
EventLoop* getLoop() const { return loop_; }
//设置线程池中线程的数量
void setThreadNum(int numThreads);
//线程初始化后回调
void setThreadInitCallback(const ThreadInitCallback& cb)
{ threadInitCallback_ = cb; }
// valid after calling start()
std::shared_ptr<EventLoopThreadPool> threadPool()
{ return threadPool_; }
//启动线程池管理器,将Acceptor::listen()加入调度队列
void start();
//如果有新的客户端连接建立或者请求关闭连接,则调用->connectionCallback_。会在新建一个TcpConnection时传给后者,供TcpConnection使用。
void setConnectionCallback(const ConnectionCallback& cb)
{ connectionCallback_ = cb; }
//如果有消息到达时调用->MessageCallback。会在新建一个TcpConnection时传给后者,供TcpConnection使用。
void setMessageCallback(const MessageCallback& cb)
{ messageCallback_ = cb; }
//消息成功写入tcp内核缓冲区后调用->writeCompleteCallback。会在新建一个TcpConnection时传给后者,供TcpConnection使用。
void setWriteCompleteCallback(const WriteCompleteCallback& cb)
{ writeCompleteCallback_ = cb; }
private:
//传给Acceptor,Acceptor会在有新的连接到来时调用->handleRead()。
void newConnection(int sockfd, const InetAddress& peerAddr);
//移除连接。
void removeConnection(const TcpConnectionPtr& conn);
//将连接从loop中取出
void removeConnectionInLoop(const TcpConnectionPtr& conn);
//string为TcpConnection名,用于找到某个连接。
typedef std::map<string, TcpConnectionPtr> ConnectionMap;
EventLoop* loop_; // the acceptor loop
const string ipPort_;
const string name_;
//仅由TcpServer持有
std::unique_ptr<Acceptor> acceptor_;
std::shared_ptr<EventLoopThreadPool> threadPool_;
ConnectionCallback connectionCallback_;
MessageCallback messageCallback_;
WriteCompleteCallback writeCompleteCallback_;
ThreadInitCallback threadInitCallback_;
AtomicInt32 started_;
// always in loop thread
int nextConnId_;
ConnectionMap connections_;
};
} // namespace net
} // namespace muduo
#endif // MUDUO_NET_TCPSERVER_H
#include "muduo/net/TcpServer.h"
#include "muduo/base/Logging.h"
#include "muduo/net/Acceptor.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/EventLoopThreadPool.h"
#include "muduo/net/SocketsOps.h"
#include <stdio.h> // snprintf
using namespace muduo;
using namespace muduo::net;
//第三个参数为TcpServer的名称,用于记录服务器名
TcpServer::TcpServer(EventLoop* loop,
const InetAddress& listenAddr,
const string& nameArg,
Option option)
: loop_(CHECK_NOTNULL(loop)),
ipPort_(listenAddr.toIpPort()),
name_(nameArg),
acceptor_(new Acceptor(loop, listenAddr, option == kReusePort)),
threadPool_(new EventLoopThreadPool(loop, name_)),
connectionCallback_(defaultConnectionCallback),//传给TcpConnection
messageCallback_(defaultMessageCallback),//传给TcpConnection
nextConnId_(1)
{
//回调ConnectionCallback->newConnection
acceptor_->setNewConnectionCallback(
std::bind(&TcpServer::newConnection, this, _1, _2));
}
TcpServer::~TcpServer()
{
loop_->assertInLoopThread();
LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";
//这里怎么理解?
for (auto& item : connections_)
{
TcpConnectionPtr conn(item.second);
item.second.reset();
conn->getLoop()->runInLoop(
std::bind(&TcpConnection::connectDestroyed, conn));
}
}
//初始化EventLoopThreadPool中的线程数量
void TcpServer::setThreadNum(int numThreads)
{
assert(0 <= numThreads);
threadPool_->setThreadNum(numThreads);
}
//启用线程池,然后runInLoop()启用Acceptor::listen()监听
void TcpServer::start()
{
先get然后得到结果是0,然后赋值为1,以后都为1就不会进入if语句
if (started_.getAndSet(1) == 0)
{
//启动线程池,threadInitCallback_创建好所有线程后调用的回调函数
threadPool_->start(threadInitCallback_);
assert(!acceptor_->listening());
loop_->runInLoop(
//get_pointer()返回一个acceptor原生指针
std::bind(&Acceptor::listen, get_pointer(acceptor_)));
}
}
//创建一个新的TcpConnection,然后传入一些参数并给该TcpConnection命名
void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
loop_->assertInLoopThread();
EventLoop* ioLoop = threadPool_->getNextLoop();
char buf[64];
snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
++nextConnId_;
//给TcpConnection取名
string connName = name_ + buf;
LOG_INFO << "TcpServer::newConnection [" << name_
<< "] - new connection [" << connName
<< "] from " << peerAddr.toIpPort();
InetAddress localAddr(sockets::getLocalAddr(sockfd));
// FIXME poll with zero timeout to double confirm the new connection
// FIXME use make_shared if necessary
//传入该TcpConnection所属的EventLoop、TcoConnection的名称、收到的Socetfd、两端的Ip
//最后以TcpConnection的指针的形式保存
TcpConnectionPtr conn(new TcpConnection(ioLoop,
connName,
sockfd,
localAddr,
peerAddr));
connections_[connName] = conn;
//将前面提到的三个回调函数注册到TcpConnection中
conn->setConnectionCallback(connectionCallback_);
conn->setMessageCallback(messageCallback_);
conn->setWriteCompleteCallback(writeCompleteCallback_);
//关闭连接时会传入TcpServer的指针,用于删除map中的TcpConnection
//会调用Channel的CloseCallback(),进而调用TcpConnection的handleClose
//进而调用removeConnection
conn->setCloseCallback(
std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
//让runInLoop在TcpConnection所在的线程去调用
ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
}
void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
// FIXME: unsafe
loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}
//关闭连接,把fd从map中中移除,在io线程中执行queueInLoop调用connectDestroyed
void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
loop_->assertInLoopThread();
LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_
<< "] - connection " << conn->name();
size_t n = connections_.erase(conn->name());
(void)n;
assert(n == 1);
EventLoop* ioLoop = conn->getLoop();
ioLoop->queueInLoop(
std::bind(&TcpConnection::connectDestroyed, conn));
}
析构函数里的这部分代码怎么理解?
TcpServer::~TcpServer()
{
loop_->assertInLoopThread();
LOG_TRACE << "TcpServer::~TcpServer [" << name_ << "] destructing";
//这里怎么理解?
for (auto& item : connections_)
{
TcpConnectionPtr conn(item.second);
item.second.reset();
conn->getLoop()->runInLoop(
std::bind(&TcpConnection::connectDestroyed, conn));
}
}