首页 > 编程语言 >C++聊天集群服务器1

C++聊天集群服务器1

时间:2023-11-26 12:44:39浏览次数:38  
标签:ChatServer const ChatService C++ json 集群 using 服务器 include

​ 先给出整个项目的结构图:
image-20231126122841767

一、环境搭建

​ 施磊的c++聊天项目。相信已经到了这部分内容就已经能够自行搭建环境了,这里主要给出搭建的具体内容,方法自行百度。下面给出环境要求。

​ 1.json-cpp

​ 2.muduo库

​ 3.cmake

​ 4.mysql

二、CMake编写

​ 主目录下的cmake

cmake_minimum_required(VERSION 3.0)
project(chat)


#配置编译选项
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -g)

#配置最终的可执行文件输出的路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

#配置头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_SOURCE_DIR}/include/server)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty)
include_directories(${PROJECT_SOURCE_DIR}/include/server/db)
#加载子目录
add_subdirectory(src)

​ src下的:

add_subdirectory(server)

​ server目录下:

#定义一个SRC_LIST,包含了该目录下的所有源文件
aux_source_directory(. SRC_LIST)
aux_source_directory(./db DB_LIST)

#指定生成可执行文件
add_executable(ChatServer ${SRC_LIST} ${DB_LIST})

#指定需要的连接时依赖库文件
target_link_libraries(ChatServer muduo_net muduo_base mysqlclient pthread)

三、网络模块

​ 网络模块主要负责处理客户端的请求数据,主要用到了陈硕大佬的muduo库,创建了一个服务器对象,并且把相应的事件注册在epoll的树上,代码及注释如下:

#ifndef  CHATSERVER_H
#define CHATSERVER_H

#include <muduo/net/TcpServer.h>
#include <muduo/net/EventLoop.h>
using namespace muduo;
using namespace muduo::net;

//聊天服务器的主类
class ChatServer
{
    public:
    //初始化聊天服务器对象
    ChatServer(EventLoop* loop,
            const InetAddress& listenAddr,
            const string& nameArg);
    //启动服务
    void start();

    private:
    
    //上报连接相关的回调函数
    void onConnection(const TcpConnectionPtr&);
    //上报读写事件相关的回调函数
    void onMessage(const TcpConnectionPtr&,
                            Buffer*,
                            Timestamp);

    TcpServer _server;   //服务器类对象
    EventLoop *_loop;    //事件循环
};

#endif

​ chatserver.cpp:

#include "chatserver.hpp"
#include "json.hpp"

#include "chatservice.hpp"

// 函数对象绑定器
#include <functional>
#include <string>

using namespace std;
// 参数占位符
using namespace placeholders;
//json库
using json = nlohmann::json;


// 初始化聊天服务器
ChatServer::ChatServer(EventLoop *loop,
                       const InetAddress &listenAddr,
                       const string &nameArg)
    : _server(loop, listenAddr, nameArg), _loop(loop)
{
    // 注册回调连接
    _server.setConnectionCallback(bind(&ChatServer::onConnection, this, _1));

    // 注册消息回调
    _server.setMessageCallback(bind(&ChatServer::onMessage, this, _1, _2, _3));

    // 设置线程数量
    //一个I/O主Reactor线程3个逻辑工作线程
    _server.setThreadNum(4);
}

// 启动服务
void ChatServer::start()
{
    _server.start();
}

// 上报连接相关的回调函数
void ChatServer::onConnection(const TcpConnectionPtr &conn)
{

    //客户端断开连接
    if(!conn->connected())
    {
        conn->shutdown();
    }

}
// 上报读写事件相关的回调函数
void ChatServer::onMessage(const TcpConnectionPtr &conn,
                           Buffer *buffer,
                           Timestamp time)
{
    //接收json
    string buf = buffer->retrieveAllAsString();
    //数据的反序列化
    json js = json::parse(buf);
    //通过js["msgid"] 获取-》业务处理handler-》conn   js    time
    //达到的目的:完全解耦网络模块的代码和业务模块的代码
    auto msgHandler = ChatService::instance()->getHandler(js["msgid"].get<int>());
    //回调消息绑定好的事件处理器,执行业务执行。
    msgHandler(conn,js,time);
}

四、业务模块

​ 这部分处理客户端的业务逻辑

#ifndef CHATSERVICE_H
#define CHATSERVICE_H

#include <unordered_map>
#include <functional>
#include <muduo/net/TcpConnection.h>

#include "json.hpp"
using json = nlohmann::json;

//using c++11语法
using namespace std;   
using namespace muduo::net;
using namespace muduo;

//表示处理消息的事件回调类型
using MsgHandler = std::function<void(const TcpConnectionPtr &conn,json &js,Timestamp)>;

// 聊天服务器业务类
class ChatService
{
public:
    //获取单例对象的接口函数
    static ChatService* instance();

    //处理登录业务
    void login(const TcpConnectionPtr &conn,json &js,Timestamp time);
    //处理注册业务
    void reg(const TcpConnectionPtr &conn,json &js,Timestamp time);
    //获取消息对应的处理器
    MsgHandler getHandler(int msgid);
private:
    //单例模式构造函数私有化
    ChatService();

    //存储消息id和其对应的事件处理方法
    unordered_map<int,MsgHandler> _msgHandlerMap;
};

#endif

​ chatservice.cpp:

#include "chatservice.hpp"
#include "public.hpp"
#include <muduo/base/Logging.h>

using namespace muduo;

ChatService *ChatService::instance()
{
    static ChatService service;
    return &service;
}

// 注册消息以及对应的Handler回调操作
ChatService::ChatService()
{
    _msgHandlerMap.insert({LOGIN_MSG, std::bind(&ChatService::login, this, _1, _2, _3)});
    _msgHandlerMap.insert({REG_MSG, std::bind(&ChatService::reg, this, _1, _2, _3)});
}

// 处理登录业务
void ChatService::login(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    LOG_INFO << "login ok!";
}
// 处理注册业务
void ChatService::reg(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    LOG_INFO << "reg ok!";
}

// 获取消息对应的处理器
MsgHandler ChatService::getHandler(int msgid)
{
    //记录错误日志,msgid没有对应的事件处理回调
    auto it = _msgHandlerMap.find(msgid);
    if(it == _msgHandlerMap.end())
    {
        //返回一个默认的处理器,空操作
        //LOG_ERROR << "msgid:" << msgid << "can not find handler!";
        return [=](const TcpConnectionPtr &conn,json &js,Timestamp)
        {
            LOG_ERROR << "msgid:" << msgid << "can not find handler!";
        };
    }
    else
    {
        return _msgHandlerMap[msgid];   
    }
}

五、公共模块

​ 目前就只有消息枚举

image-20231126123423982

​ 过两天继续跟进。

标签:ChatServer,const,ChatService,C++,json,集群,using,服务器,include
From: https://www.cnblogs.com/dwinternet/p/17856747.html

相关文章

  • C/C++ 常用加密与解密算法
    计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性,常常需要使用加密和解密算法。C++是一种广泛使用的编程语言,提供了许多加密和解密算法的实现。本文将介绍一些在C++中常用的加密与解密算法,这其中包括Xor异或、BASE64、AES、MD5、SHA256、RS......
  • 企业计算机服务器中了mkp勒索病毒怎么办?Mkp勒索病毒解密数据恢复
    网络技术的不断发展,为企业的生产运营提供了坚实的基础,但随之而来的网络安全威胁也不断增加,影响了企业的正常生产生活。近期,云天数据恢复中心陆续接到很多企业的求助,企业计算机服务器遭到了mkp勒索病毒攻击,导致企业的所有数据被加密无法正常使用。经过云天数据恢复中心对mkp勒索病毒......
  • C++ Boost库
    《C++Boost库》1.Preface  cxmsc2.Boost库编译解压boost源码压缩目录Windows平台下,打开cmd,运行脚本bootstrap.bat脚本生成b2.exe文件boost需要通b2.exe来自动编译源码;在编译之前,需要指定一些列参数:首先可通过--help命令来查看相关的参数#展示boost里所有的库b2......
  • C++ 二叉树 家谱
    实验三树家谱文档实验说明要求完成的功能如下,测试输出如图所示:(1)输入一棵二叉树的括号表示法,完成树的构建(2)使用后序遍历递归算法遍历二叉树并输出(3)使用先序遍历非递归算法遍历二叉树并输出(4)指定家谱中的某一成员,输出其所有长辈测试例:输入:A(B(C(E,F),D(G(M,N),H))......
  • C++ 通过SQLite实现命令行工具
    本文介绍了一个基于C++、SQLite和Boost库的简单交互式数据库操作Shell。该Shell允许用户通过命令行输入执行各种数据库操作,包括添加、删除主机信息,设置主机到特定主机组,以及显示主机和主机组列表。通过调用SQLite3库实现数据库连接和操作,以及使用Boost库进行字符串解析......
  • 试题 D: 本质上升序列(C/C++)
    题目描述:小蓝特别喜欢单调递增的事物。在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。例如,在字符串lanqiao中,如果取出字符n和q,则nq组成一个单调递增子序列。类似的单调递增子序列还有lnq......
  • RabbitMQ -- 集群(二)
    镜像队列队列创建只在创建的机器上出现,不会出现在其他节点上,需要创建镜像队列,将队列备份到其他节点,可以备份到其他节点或者全部节点创建:在任意一个节点上添加一个policy即可在Web管理界面设置:admin->policies->Add/updateapolicy->Name:mirror-twoPattern:^mirror......
  • C#调用C++类库的几种方式
    1、 直接调用C++类库中的公共方法使用DllImport特性对方法进行调用,比如一个C++类库SampleCppWrapper.dll中的公共方法:extern"C"__declspec(dllexport)int__stdcallAdd(intn1,intn2);__stdcall表示调用约定:参数都是从右向左通过堆栈传递, 函数调用在返回前要由被调......
  • C/C++ 通过SQLiteSDK增删改查
    SQLite,作为一款嵌入式关系型数据库管理系统,一直以其轻量级、零配置以及跨平台等特性而备受青睐。不同于传统的数据库系统,SQLite是一个库,直接与应用程序一同编译和链接,无需单独的数据库服务器进程,实现了数据库的零配置管理。这种设计理念使得SQLite成为许多嵌入式系统、移动应用和......
  • c++ 为什么引入函数对象?
    C++引入函数对象主要是因为函数对象具有以下优势:函数对象可以有自己的状态:我们可以在类中定义状态变量,这样一个函数对象在多次的调用中可以共享这个状态。但是函数调用没这种优势,除非它使用全局变量来保存状态。函数对象有自己特有的类型,而普通函数无类型可言:这种特性对......