系列文章目录:C++ asio网络编程-CSDN博客
1、服务器架构设计
2、单例模板类
我们的LogicSystem类为单例类,可以只把这个类写为单例,也可以写一个单例模板类,让其它类继承它就可以形成单例。这里选择第二种,因为后面可能还会实现其他的单例类。
cpp
#pragma once
#include <memory>
#include <mutex>
#include <iostream>
template <typename T>
class Singleton
{
public:
~Singleton() {
std::cout << "singleton destruct" << std::endl;
}
static std::shared_ptr<T> getInstance() {
static std::once_flag s_flag;
std::call_once(s_flag, [&]() {
_instance = std::shared_ptr<T>(new T);
});
return _instance;
}
void printAddress() {
std::cout << _instance->get() << std::endl;
}
protected:
Singleton() = default;
Singleton(const Singleton<T>&) = delete;
Singleton& operator = (const Singleton<T>& st) = delete;
static std::shared_ptr<T> _instance;
};
template <typename T>
std::shared_ptr<T> Singleton<T>::_instance = nullptr;
C++基础好的同学应该很容易看明白,有不明白的地方可以利用一些ai工具解读一下,也很简单。
3、LogicSystem类
cpp
#pragma once
#include "Singleton.h"
#include <queue>
#include <thread>
#include "const.h"
#include "Session.h"
#include <map>
#include <functional>
#include <json/json.h>
#include <json/value.h>
#include <json/reader.h>
class LogicNode;
class Session;
typedef std::function<void(std::shared_ptr<Session>, const short& msg_id, const std::string& msg_data)> FunCallBack;
class LogicSystem : public Singleton<LogicSystem>
{
friend class Singleton<LogicSystem>;
public:
~LogicSystem();
void postMsgToQue(std::shared_ptr<LogicNode> msg);
private:
LogicSystem();
void registerCallBacks();
void helloWordCallBack(std::shared_ptr<Session>, const short& msg_id, const std::string& msg_data);
void dealMsg();
std::queue<std::shared_ptr<LogicNode>> _msg_que; // 逻辑队列
std::mutex _mutex;
std::condition_variable _consume; // 条件变量,控制当逻辑队列为空时保证线程暂时挂起等待,不要干扰其他线程
std::thread _worker_thread;
bool _b_stop; // 停止信号,控制逻辑类中止工作线程
std::map<short, FunCallBack> _fun_callback; // 回调函数的map,根据id查找对应的逻辑处理函数
};
cpp
#include "LogicSystem.h"
LogicSystem::~LogicSystem()
{
_b_stop = true;
_consume.notify_one();
_worker_thread.join();
}
void LogicSystem::postMsgToQue(std::shared_ptr<LogicNode> msg)
{
std::unique_lock<std::mutex> ulock(_mutex);
_msg_que.push(msg);
if (_msg_que.size() == 1) {
_consume.notify_one();
}
}
LogicSystem::LogicSystem() : _b_stop(false)
{
registerCallBacks();
_worker_thread = std::thread(&LogicSystem::dealMsg, this);
}
void LogicSystem::registerCallBacks()
{
_fun_callback[MSG_HELLO_WORD] = std::bind(&LogicSystem::helloWordCallBack, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
}
void LogicSystem::helloWordCallBack(std::shared_ptr<Session> session, const short& msg_id, const std::string& msg_data)
{
Json::Reader reader;
Json::Value root;
reader.parse(msg_data, root);
std::cout << "receive msg id is " << root["id"].asInt() << "msg data is "
<< root["data"].asString() << std::endl;
root["data"] = "server has receive msg: " + root["data"].asString();
std::string return_str = root.toStyledString();
session->send(return_str, root["id"].asInt());
}
void LogicSystem::dealMsg()
{
for (;;) {
std::unique_lock<std::mutex> ulock(_mutex);
// 队列为空并且正在处理消息则用条件变量等待
while (_msg_que.empty() && !_b_stop) {
_consume.wait(ulock); // 先释放资源再解锁
}
// 关闭状态时,取出逻辑队列所有数据及时处理,并且退出循环
if (_b_stop) {
while (!_msg_que.empty()) {
auto msg_node = _msg_que.front();
std::cout << "receive msg id: " << msg_node->_recvNode->_msg_id << std::endl;
auto call_back_iter = _fun_callback.find(msg_node->_recvNode->_msg_id);
if (call_back_iter == _fun_callback.end()) {
_msg_que.pop();
continue;
}
call_back_iter->second(msg_node->_session,
msg_node->_recvNode->_msg_id,
std::string(msg_node->_recvNode->_data, msg_node->_recvNode->_cur_len));
_msg_que.pop();
}
break;
}
// 没有停服,并且队列有数据
auto msg_node = _msg_que.front();
std::cout << "receive msg id: " << msg_node->_recvNode->_msg_id << std::endl;
auto call_back_iter = _fun_callback.find(msg_node->_recvNode->_msg_id);
if (call_back_iter == _fun_callback.end()) {
_msg_que.pop();
continue;
}
call_back_iter->second(msg_node->_session,
msg_node->_recvNode->_msg_id,
std::string(msg_node->_recvNode->_data, msg_node->_recvNode->_cur_len));
_msg_que.pop();
}
}
MSG_HELLO_WORD定义在const.h中,表示消息id
cpp
enum MSG_IDS {
MSG_HELLO_WORD = 1001
};
4、逻辑节点
在Session.h中,我们可以添加一个逻辑节点类
cpp
class LogicNode
{
friend class LogicSystem;
public:
// 第二个参数是为了防止session被提前释放
LogicNode(std::shared_ptr<Session>, std::shared_ptr<RecvNode>);
private:
std::shared_ptr<Session> _session;
std::shared_ptr<RecvNode> _recvNode;
};
cpp
LogicNode::LogicNode(std::shared_ptr<Session> session, std::shared_ptr<RecvNode> recvNode)
: _session(session), _recvNode(recvNode)
{
}