当前位置:网站首页>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());
}
}
边栏推荐
- MySQL数据库索引
- 1063 Set Similarity
- Network learning infrared module, 8-way emission independent control
- 合宙ESP32C3硬件配置信息串口打印輸出
- HDU - 2586 How far away ?(倍增LCA)
- [attack and defense world web] difficulty four-star 12 point advanced question: flatscience
- Proof of green Tao theorem (2): generalization of von Neumann theorem
- The third slam Technology Forum - Professor wuyihong
- Chapter 2 回归
- 1063 Set Similarity
猜你喜欢

支付宝常用接口统一封装,可直接支付参数使用(适用于H5、PC、APP)

MySql的DDL和DML和DQL的基本语法

Problems and abuse of protocol buffers

CMake的学习

LeetCode热题 HOT52-100

Synchronized同步锁的基本原理

TCP半连接队列和全连接队列(史上最全)

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.

深入浅出边缘云 | 1. 概述

集群聊天服務器:數據庫錶的設計
随机推荐
第三届SLAM技术论坛-吴毅红教授
一时跳槽一时爽,一直跳槽一直爽?
Chapter 3 business function development (creating clues)
Protocol buffers 的问题和滥用
Failed to introspect Class FeignClientFactoryBean 异常排查
Chapter1 data cleaning
vite3学习记录
[continuous update] collection of raspberry pie startup and failure series
Edge cloud | 1. overview
Unity - 3D mathematics -vector3
OOM机制
Basic knowledge of mobile phone testing
Trial record of ModelBox end cloud collaborative AI development kit (rk3568) (II)
One of QT desktop whiteboard tools (to solve the problem of unsmooth curve -- Bezier curve)
1062 Talent and Virtue
Green-Tao 定理的证明 (2): Von Neumann 定理的推广
【攻防世界WEB】难度四星12分进阶题:FlatScience
高数下|二重积分的计算3|高数叔|手写笔记
1061 Dating
"Pulse" to the future! Huawei cloud Mrs helps smooth migration to the cloud