当前位置:网站首页>Cluster chat server: chatservice business layer
Cluster chat server: chatservice business layer
2022-07-23 21:18:00 【_ Soren】
List of articles
Design callback
Use the binder to realize
// The type of event callback method that handles the message
using MsgHandler = std::function<void(const TcpConnectionPtr& conn, json& js, Timestamp)>;
Decouple network layer and business layer
In the communication module , One field is msgid, It represents the message type of communication between the server and the client , stay public.hpp in
enum EnMsgType
{
LOGIN_MSG = 1, // Login message
LOGIN_MSG_ACK, // Login response
REG_MSG, // Sign up for messages
REG_MSG_ACK, // Register response
ONE_CHAT_MSG, // Chat messages
ADD_FRIEND_MSG, // Add buddy
CREATE_GROUP_MSG, // Create groups
ADD_GROUP_MSG, // Join the group
GROUP_CHAT_MSG, // Group chat
LOGINOUT_MSG // Cancellation
};
Depending on the type of message , You can add a hash table in the business layer , The key is the corresponding message , Value is the method that should be called when different types of events occur .
// Store messages ID And its corresponding business processing method
unordered_map<int, MsgHandler> _msgHandlerMap;
_msgHandlerMap.insert({
LOGIN_MSG, std::bind(&ChatService::login, this, _1, _2, _3)});
_msgHandlerMap.insert({
REG_MSG, std::bind(&ChatService::reg, this, _1, _2, _3)});
_msgHandlerMap.insert({
ONE_CHAT_MSG, std::bind(&ChatService::oneChat, this, _1, _2, _3)});
_msgHandlerMap.insert({
ADD_FRIEND_MSG, std::bind(&ChatService::addFriend, this, _1, _2, _3)});
_msgHandlerMap.insert({
CREATE_GROUP_MSG, std::bind(&ChatService::createGroup, this, _1, _2, _3)});
_msgHandlerMap.insert({
ADD_GROUP_MSG, std::bind(&ChatService::addGroup, this, _1, _2, _3)});
_msgHandlerMap.insert({
GROUP_CHAT_MSG, std::bind(&ChatService::groupChat, this, _1, _2, _3)});
_msgHandlerMap.insert({
LOGINOUT_MSG, std::bind(&ChatService::loginOut, this, _1, _2, _3)});
The network layer depends on the message ID To determine and implement handler
// To achieve : Completely decouple the code of the network module and the code of the business module
// adopt js["msgid"]( One ID Bind a module ) obtain -》 Business handler-》 conn js time
auto msgHandler = ChatService::instance()->getHandler(js["msgid"].get<int>());
// Callback message bound event handler , To execute the corresponding business processing
msgHandler(conn, js, time);
In this way, when developing in the business layer , Just deal with the business wholeheartedly , It doesn't matter how these business methods are called .
How to get the processor corresponding to the message
// Get the processor corresponding to the message
MsgHandler ChatService::getHandler(int msgid)
{
// Log errors ,msgid There is no corresponding event handling callback
auto it = _msgHandlerMap.find(msgid);
if (it == _msgHandlerMap.end())
{
// Returns a default processor ( Empty operation )
return [=](const TcpConnectionPtr& conn, json& js, Timestamp) {
LOG_ERROR << "msgid: " << msgid << " can not find handler!";
};
}
else // If it works
{
return _msgHandlerMap[msgid];
}
}
Business level header file
These businesses are currently available , Sign in 、 Cancellation 、 register 、 add friends 、 One on one chat 、 Create group chat 、 Join the group chat 、 Group chat, etc .
#ifndef CHATSERVICE_H
#define CHATSERVICE_H
#include <muduo/net/TcpConnection.h>
#include <unordered_map>
#include <functional>
#include <mutex>
#include "userModel.hpp"
#include "offlineMessageModel.hpp"
#include "friendModel.hpp"
#include "groupModel.hpp"
#include "redis.hpp"
using namespace std;
using namespace muduo;
using namespace muduo::net;
#include "json.hpp"
using json = nlohmann::json;
// The type of event callback method that handles the message
using MsgHandler = std::function<void(const TcpConnectionPtr& conn, json& js, Timestamp)>;
// Chat server business class
// The singleton pattern
class ChatService
{
public:
// Get the interface function of the singleton object
static ChatService* instance();
// Processing login business
void login(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Deal with registration business
void reg(const TcpConnectionPtr& conn, json& js, Timestamp time);
// One to one chat business
void oneChat(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Add friend business
void addFriend(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Create group business
void createGroup(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Join group business
void addGroup(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Group chat service
void groupChat(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Cancellation business
void loginOut(const TcpConnectionPtr& conn, json& js, Timestamp time);
// Get the processor corresponding to the message
MsgHandler getHandler(int msgid);
// Handle client exception exit
void clientCloseException(const TcpConnectionPtr& conn);
// Server exception , Business reset method
void reset();
// from redis Get subscribed messages from message queue
void handleRedisSubscribeMessage(int userid, string msg);
private:
ChatService();
// Store messages ID And its corresponding business processing method
unordered_map<int, MsgHandler> _msgHandlerMap;
// Store the communication connection of online users
unordered_map<int, TcpConnectionPtr> _userConnMap;
// Define mutexes , Guarantee _userConnMap Thread safety for
std::mutex _connMutex;
// Data operation class object
UserModel _userModel;
OfflineMsgModel _offlineMsgModel;
FriendModel _friendModel;
GroupModel _groupModel;
// redis Action object
Redis _redis;
};
#endif
Business layer example : Login operation
First, according to the user's id Find out the user's information ( There are data operation class objects in the private members of the header file above ), if id And the password is correct , Then log in , If the status is online , Then send an error message 【 The user is logged in 】; If not online , Then log in , First, change the user status , Then it displays whether the user has an offline message , Then display the user's friend information and group messages , This business is added according to personal ideas ; if id Or if the password is wrong, an error message will appear 【id Or wrong password 】.
// Processing login business id pwd
void ChatService::login(const TcpConnectionPtr& conn, json& js, Timestamp time)
{
// LOG_INFO << "do login service!!!";
int id = js["id"];
string pwd = js["password"];
User user = _userModel.query(id);
if (user.getId() == id && user.getPwd() == pwd)
{
json response;
if (user.getState() == "online")
{
// The user is logged in , Duplicate login is not allowed
response["msgid"] = LOGIN_MSG_ACK;
response["errno"] = 2;
response["errmsg"] = "This account is using, please use other account: ";
}
else
{
// Login successful , Record user connection information , To ensure thread safety
{
lock_guard<mutex> lock(_connMutex);
_userConnMap.insert({
id, conn});
}
// id After the user logs in successfully , towards redis subscribe channel
_redis.subscribe(id);
// Login successful , Update user status information ,state offline->online
user.setState("online");
_userModel.updateState(user);
response["msgid"] = LOGIN_MSG_ACK;
response["errno"] = 0;
response["id"] = user.getId();
response["name"] = user.getName();
// Check whether the user has offline messages
vector<string> nums = _offlineMsgModel.query(id);
if (!nums.empty())
{
response["offlineMsg"] = nums;
// After reading the user's offline message , Delete these messages
_offlineMsgModel.remove(id);
}
// Query the user's friend information and return
vector<User> userNums = _friendModel.query(id);
if (!userNums.empty())
{
vector<string> nums2;
for (User& user : userNums)
{
json js;
js["id"] = user.getId();
js["name"] = user.getName();
js["state"] = user.getState();
nums2.emplace_back(js.dump());
}
response["friends"] = nums2;
}
// Query the group messages of users
vector<Group> groupuserVec = _groupModel.queryGroups(id);
if (!groupuserVec.empty())
{
// group:[{groupid:[xxx, xxx, xxx, xxx]}]
vector<string> groupV;
for (Group& group : groupuserVec)
{
json grpjson;
grpjson["id"] = group.getId();
grpjson["groupname"] = group.getName();
grpjson["groupdesc"] = group.getDesc();
vector<string> userV;
for (GroupUser& user : group.getUsers())
{
json js;
js["id"] = user.getId();
js["name"] = user.getName();
js["state"] = user.getState();
js["role"] = user.getRole();
userV.emplace_back(js.dump());
}
grpjson["users"] = userV;
groupV.emplace_back(grpjson.dump());
}
response["groups"] = groupV;
}
}
conn->send(response.dump());
}
else
{
// Login failed ( Users exist , Wrong password )
json response;
response["msgid"] = LOGIN_MSG_ACK;
response["errno"] = 1;
response["errmsg"] = "id or password is invalid!";
conn->send(response.dump());
}
}
边栏推荐
- vite3学习记录
- scala编程(初级)
- 高数下|二重积分的计算3|高数叔|手写笔记
- Microservice architecture vs single service architecture [what can Huawei cloud service do in the microservice mode]
- 1309_STM32F103上增加GPIO的翻转并用FreeRTOS调度测试
- Now I don't know how to synchronize at all
- 1061 Dating
- TCP half connection queue and full connection queue (the most complete in History)
- 《迷失》stray工人帽子获得方法 工人安全帽在哪里?
- 2022-7-23 12点 程序爱生活 小时线顶背离出现,保持下跌趋势,等待反弹信号出现。
猜你喜欢

TypeScript基础

Hezhou esp32c3 hardware configuration information serial port printout

At 12 o'clock on July 23, 2022, the deviation from the top of the line of love life hour appeared, maintaining a downward trend and waiting for the rebound signal.

One of QT desktop whiteboard tools (to solve the problem of unsmooth curve -- Bezier curve)
![[attack and defense world web] difficulty four-star 12 point advanced question: flatscience](/img/fc/6648116f1bb47f1888035796fa5a58.png)
[attack and defense world web] difficulty four-star 12 point advanced question: flatscience

对接湖南CA使用U_KEY登录

Day109.尚医通:集成Nacos、医院列表、下拉列表查询、医院上线功能、医院详情查询

1309_STM32F103上增加GPIO的翻转并用FreeRTOS调度测试

【愚公系列】2022年06月 .NET架构班 084-微服务专题 Abp vNext微服务通信

Unity—3D数学-Vector3
随机推荐
WinDbg practice -- Introduction
模块化开发
Protocol buffers 的问题和滥用
Hezhou esp32c3 hardware configuration information serial port printout
The common interfaces of Alipay are uniformly encapsulated and can be used directly for payment parameters (applicable to H5, PC, APP)
Major upgrade of openim - group chat reading diffusion model release group management function upgrade
Junior intern, ByteDance, after sharing, has been offered
Tell me the top ten securities companies? Is it safe to open an account online?
Problems and abuse of protocol buffers
剑指 Offer II 115. 重建序列 : 拓扑排序构造题
集群聊天服务器:如何解决跨服务器通信问题 | redis发布-订阅
High numbers | calculation of triple integral 2 | high numbers | handwritten notes
Edge cloud | 1. overview
TypeScript基础
[shader realizes roundwave circular ripple effect _shader effect Chapter 6]
基于速度、复杂性等因素比较KernelSHAP和TreeSHAP
vite3学习记录
一道golang中关于for range常见坑的面试题
BroadCast(广播)
Protocol buffers 的问题和滥用