介绍:可以直接当成一个服务器了,你只需要设置loop,绑定地址,服务器名称,SO_REUSEPORT是否开启就行了。如果想要运用多个I/O线程池,在start()函数之前调用setThreadNum(int numThreads)设置线程池中的线程数就可以了.
1.TcpServer.h文件
///
///该类即支持单线程也支持多线程
///该类是一个接口类,所以不暴露太多细节
class TcpServer : noncopyable
{
public:
///线程初始化函数,并不一定需要
typedef std::function<void(EventLoop*)> ThreadInitCallback;
enum Option
{
kNoReusePort,
kReusePort,
};
//TcpServer(EventLoop* loop, const InetAddress& listenAddr);
TcpServer(EventLoop* loop,
const InetAddress& listenAddr,
const string& nameArg,
Option option = kNoReusePort);
~TcpServer(); // force out-line dtor, for std::unique_ptr members.
const string& ipPort() const { return ipPort_; }
const string& name() const { return name_; }
EventLoop* getLoop() const { return loop_; }
///设置I/O线程池中线程的数量,一定在start函数前调用
///这些线程总是接收新的连接
///参数为0时:没有I/O线程被建立,参数为0时默认值
///参数为N时:有多个线程,新的连接被 基于轮转法的I/O线程池分配。
void setThreadNum(int numThreads);
///设置线程初始化函数
void setThreadInitCallback(const ThreadInitCallback& cb)
{ threadInitCallback_ = cb; }
/// valid after calling start()
std::shared_ptr<EventLoopThreadPool> threadPool()
{ return threadPool_; }
///如果处于监听状态就启动服务器
/// 该函数可以被调用多次
/// 线程安全的函数
void start();
/// 设置建立连接成功后的回调
/// 不是线程安全的
void setConnectionCallback(const ConnectionCallback& cb)
{ connectionCallback_ = cb; }
/// 设置消息回调
/// 不是线程安全的
void setMessageCallback(const MessageCallback& cb)
{ messageCallback_ = cb; }
///设置写回调
/// 不是线程安全的
void setWriteCompleteCallback(const WriteCompleteCallback& cb)
{ writeCompleteCallback_ = cb; }
private:
/// acceptor设置的回调
void newConnection(int sockfd, const InetAddress& peerAddr);
/// Thread safe.
void removeConnection(const TcpConnectionPtr& conn); ///移除已建立的连接
/// Not thread safe, but in loop
void removeConnectionInLoop(const TcpConnectionPtr& conn); ///实际上的移除连接的操作
typedef std::map<string, TcpConnectionPtr> ConnectionMap; ///已建立的连接map
EventLoop* loop_; // the acceptor loop
const string ipPort_; //本地地址
const string name_; //服务名字
std::unique_ptr<Acceptor> acceptor_; //起到监听作用的对象accept()
std::shared_ptr<EventLoopThreadPool> threadPool_; ///I/O线程池
ConnectionCallback connectionCallback_; ///内部就是输出本地的地址,对端的地址,连接状态
MessageCallback messageCallback_;
WriteCompleteCallback writeCompleteCallback_;
ThreadInitCallback threadInitCallback_; ///线程初始化函数
AtomicInt32 started_;
// always in loop thread
int nextConnId_;
ConnectionMap connections_;
};
2.TcpServer.cc文件
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)),///构造一个Acceptor对象
threadPool_(new EventLoopThreadPool(loop, name_)), ///构造一个I/O线程池对象
connectionCallback_(defaultConnectionCallback), ///该回调函数输出本地地址,对端地址,连接状态
messageCallback_(defaultMessageCallback), ///将buffer中的读索引和写索引重置
nextConnId_(1) ///下一个建立的连接ID位1
{
acceptor_->setNewConnectionCallback(
std::bind(&TcpServer::newConnection, this, _1, _2)); ///设置建立连接的回调函数
}
TcpServer::~TcpServer()
{
loop_->assertInLoopThread(); //断言是否在loop线程
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));
}
}
///设置I/O线程池中的线程数量
void TcpServer::setThreadNum(int numThreads)
{
assert(0 <= numThreads);
threadPool_->setThreadNum(numThreads);
}
//开启服务器
void TcpServer::start()
{
if (started_.getAndSet(1) == 0)
{
threadPool_->start(threadInitCallback_); ///I/O线程池开始工作
assert(!acceptor_->listening());
loop_->runInLoop(
std::bind(&Acceptor::listen, get_pointer(acceptor_))); ///acceptor_启动监听任务
}
}
///建立新连接
void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
{
loop_->assertInLoopThread(); ///断言是否在loop线程
EventLoop* ioLoop = threadPool_->getNextLoop(); ///内部采用轮转法,决定将要选择的I/O线程
char buf[64];
snprintf(buf, sizeof buf, "-%s#%d", ipPort_.c_str(), nextConnId_);
++nextConnId_; ///下一个连接的id
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
TcpConnectionPtr conn(new TcpConnection(ioLoop,
connName,
sockfd,
localAddr,
peerAddr)); ///建立新连接
connections_[connName] = conn;
conn->setConnectionCallback(connectionCallback_); ///输出本地地址,对端地址,连接状态
conn->setMessageCallback(messageCallback_); ///将buffer的读索引和写索引重置
conn->setWriteCompleteCallback(writeCompleteCallback_); ///写完成后调用的回调
///销毁链接
conn->setCloseCallback(
std::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn)); ///开启监听读事件
}
void TcpServer::removeConnection(const TcpConnectionPtr& conn)
{
// FIXME: unsafe 在主loop线程中执行
loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}
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));
}