我是靠谱客的博主 英勇白猫,最近开发中收集的这篇文章主要介绍基于EventLoop的tcp服务端 C++实现(二) ——服务端TcpServer的模块设计描述,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
学习github上的项目 flamingo 自己的笔记。
flamingo原作者的csdn是: analogous_love
flamingo是多线程的,但是本人能力有限,只是单线程的还算能理解一点。
自己参照flamingo实现的基于epoll的单线程服务端,git地址:https://gitee.com/storm_zy/StServerFrame
实现了简单的echo功能,很多代码直接拷贝自flamingo。
一、如何设计TcpServer——功能上来说
- 一个TcpServer需要至少一个监听的端口(Listener)。
- 需要提供新连接到来时的处理方法,即将连接加入到自己的列表中进行维护等等。
- 需要维护自己的连接列表 TcpConnections。
- 需要处理过时失效的连接 。
- 提供对业务层的回调接口connectCallBack,以便将建立的TcpConnection告知上层的业务层。
- 业务层通过TcpConnetion来建立业务层的Session,然后实现业务的接入。
二、如何设计TcpServer——流程上来说
- 首先需要确定监听的端口和地址。
- 将新连接建立OnNewConnection(int fd)函数,用来设置到Listener对象的回调函数,在接收到新连接的时候可以接入到本TcpServer中。需要在 连接建立后调用 connectCallBack 接入到业务层。
- 新建立的连接添加到 connections列表中,进行维护。
- 需要有 start和stop函数,就是开始和结束函数,命名随意。
- 在start函数中,将Listener开启监听。
- 在stop函数中,将connections列表清理,并关闭Listener。
三、伪码实现
1 类设计
// 至于函数命名,因为是参考的 flamingo的代码,有的是直接拷贝的,有的是自己写的,所以有点乱。。。
class CListener;
class CTcpServer
{
public:
typedef std::function<void(CTcpConnection *)> ConnectionCallBack;
typedef std::function<void()> DailyResCleanCallBack;
CTcpServer(CEventLoop *loop, const std::string& ip, st_port_t port);
~CTcpServer();
public:
void start();
void stop();
void closeConnection(CTcpConnection *c);
void OnNewConnection(int fd);
void OnConnectionClose(CTcpConnection *c);
void BindSession(CTcpSession *session, CTcpConnection *c);
void HandleDailyResCleanUp(CEventLoop *loop); // 处理需要关闭的连接等
private:
bool AddConnection(CTcpConnection *c);
void RemoveConnetion(CTcpConnection *c);
void CleanConnetions();
public:
void setConnectionCallBack(const ConnectionCallBack& cb) { connectionCallBack_ = cb; }
void setDailyCleanUpCallBack(const DailyResCleanCallBack& cb) { dailyResCleanUpCallBack_ = cb; }
private:
ConnectionCallBack connectionCallBack_;
DailyResCleanCallBack dailyResCleanUpCallBack_;
private:
typedef std::map<int, CTcpConnection*> ConnectionMap;
typedef std::vector<CTcpConnection *> ConnectionList;
ConnectionMap m_connections;
ConnectionList m_needDelConnections;
CEventLoop *m_loop;
bool m_stoped;
CListener *m_listener;
};
2 构造函数和析构函数
CTcpServer::CTcpServer(CEventLoop *loop, const std::string& ip, st_port_t port) :
m_loop(loop), m_listener(new CListener(loop, ip, port))
{
m_listener->setNewConnectionCallBack(std::bind(&CTcpServer::OnNewConnection, this, std::placeholders::_1));
m_loop->setRuntimeCallBack(std::bind(&CTcpServer::HandleDailyResCleanUp, this, std::placeholders::_1));
}
CTcpServer::~CTcpServer()
{
this->CleanConnetions();
}
3 开始和停止
void CTcpServer::start()
{
m_stoped = false;
m_listener->StartListening();
}
void CTcpServer::stop()
{
m_listener->Close();
m_stoped = true;
if (m_loop)
m_loop->stop();
this->CleanConnetions();
}
4 新连接建立回调函数,在Listener中调用
void CTcpServer::OnNewConnection(int fd)
{
CTcpConnection *conn = new CTcpConnection(m_loop, fd);
if (!AddConnection(conn)) {
return;
}
在TcpConnection中处理关闭时会调用该回调。CTcpServer::OnConnectionClose就是要将关闭的连接添加到待删除连接列表。
conn->setCloseCallBack(std::bind(&CTcpServer::OnConnectionClose, this, std::placeholders::_1));
CSocket s(fd);
s.SetNonBlock(true);
conn->connectEstablished();
if (connectionCallBack_)
connectionCallBack_(conn);
}
5 业务层绑定回调函数,业务层的类需要集成 CTcpSession然后重写其读写函数。
将方法绑定到TcpConnection上之后,就会在 EventLoop中调用相应的方法,以此来实现回调。
void CTcpServer::BindSession(CTcpSession *session, CTcpConnection *c)
{
c->setMessageCallBack(std::bind(&CTcpSession::OnRead, session, std::placeholders::_1, std::placeholders::_2));
c->setWriteCompleteCallBack(std::bind(&CTcpSession::OnWriteComplete, session, std::placeholders::_1));
c->addSession(session);
}
6 日常检查过时连接并清理
void CTcpServer::HandleDailyResCleanUp(CEventLoop *loop)
{
if (dailyResCleanUpCallBack_)
dailyResCleanUpCallBack_();
size_t len = m_needDelConnections.size();
if (len) {
for (size_t i = 0; i < len; ++i)
{
CTcpConnection *c = m_needDelConnections.back();
m_needDelConnections.pop_back();
SAFE_DEL(c);
}
}
}
*以上只是伪码,示例大概怎样使用。
欢迎关注 [懒人漫说] 公众号,分享Java、Android、C/C++ 技术,包括基础、自己遇到的问题解决过程。
当然如果关注并留言问题的话,我们力所能及的话会帮你解决并回复哟。我们和你一样,是正在成长的程序员,我们也会分享自己的成长路上的感想,希望可以和你一起努力成长。
最后
以上就是英勇白猫为你收集整理的基于EventLoop的tcp服务端 C++实现(二) ——服务端TcpServer的模块设计描述的全部内容,希望文章能够帮你解决基于EventLoop的tcp服务端 C++实现(二) ——服务端TcpServer的模块设计描述所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复