集群C++聊天服务器

1.json

一种数据序列化的方式。先将数据==》json对象=》文本

格式

原先的js对象,出不了门。只能在自己的电脑是看地址读数据。现在给它拍扁成文本形式,这样在另一台电脑上才有人可以认出它嘛。

{},【】," "这些符号都有特定的寓意。

用{ }括起来的,

js["id"] = { 1 , 2 , 3 , 4 , 5 };{ }是初始化列表的代表。

{"id":[1,2,3,4,5],"name":"zhangsan"}则是它原本的功能,里面必须包含字符串(" ")。

还有json打印出来,就是key : value。有这个:就是json的特点。

2.muduo网络库

框架搭起来后,我们只需要关注2个点。

在当前chatServer服务器类的构造函数当中,注册处理连接 的回调函数和处理读写 事件的回调函数。

构造一个chatServer,网络模块。

3.cmake

cMakeList.txt

cmake . 根据CMakeList.txt生成Makefile文件
make执行Makefile文件,(Makefile文件就是集成了很多编译命令)生成可执行程序

4.Mysql相关

1.sql语句先在mysql服务端建库建表

2.用c++将Mysql封装起来,作为数据客户端层

这样调用Mysql的对象会遵循RAII。

在服务器端也能连接db,敲sql命令了。

3.用user,userModel类将业务层和数据层解耦

业务层往只会看到操作UserModel往User类中再增加一行。

UserModel才会看到对数据层的操作。

5.业务模块与网络模块解耦

回调函数 +Map 将网络模块,业务模块解耦。

解耦很容易理解,就是在网络模块中,不会出现业务模块的函数(虽然底层调用的还是void login()),用msgHandler当做盲盒。
chatserver不知道盲盒中是什么,只知道要执行盲盒。
chatservice注册盲盒中是什么。

业务


1. 注册业务

业务层ChatSevice::reg()通过User UserModel::insert(int user)来注册

2. 登录业务

业务层ChatSevice::login( )通过User UserModel::query(int id)userModel.updateState(user)来登录。

(比如id 1在表中吗,如果在就将其state设置为online)。

另外,在业务层中放一个

cpp 复制代码
//存储在线用户的通信连接
    unordered_map<int,TcpConnectionPtr> _userConnMap;

3.客户端异常退出业务

业务层ChatService::clientCloseExecption通过userModel.updateState(user)来实现退出。

更新用户状态信息 user表中状态改为offline

同时,从userConnMap中删除用户的连接信息

4.1对1聊天业务+离线消息存储业务

A向B发消息。A通过tcpConnectionA发给服务器,服务器再通过tcpConnectionB发给B(userConnMap的作用来了)

业务层ChatService::oneChat通过userConnMap找到另一个tcpConnection

5.离线消息存储业务

A向B发消息,但是B离线。

业务层通过offlineMsgModel操作层,往B的offlineMsg表中添加数据。

B上线后通过OfflineMsgModel::query(int userid)可以查到

6.服务器异常退出

服务器异常是ctrl+c触发的,所以没有msgid。没有在msgHandleMap查找

,而是直接通过signal(SIGINT,resetHandler)捕获。

7.添加好友业务

添加好友后,每次用户登录会返回离线消息和好友列表。

在业务层通过addFriend()中的 FriendModel::insert+vector<User> FriendModel::query(int userid)实现。

  • friendModel操作层 FriendModel::insert添加好友关系
  • vector<User> FriendModel::query(int userid)通过userid,查询朋友的信息.
    userId是1的人的朋友的用户信息,
    sql语句如下:
sql 复制代码
select a.id,a.name,a.state 
from user a 
inner join friend b 
on b.friendid=a.id 
where b.userid = %d

8. 群组功能业务

麻烦死了,我直接将原本的AllGroup表和GroupUser表合并一个Group表。

合并出来的表还可以直接继承 user表。爽。

用GroupModel操作Group表。

实现4个功能:

  1. 创建群。再创建一个Group表。
  2. 加入群。就是在Group表中插入一行。insert into group
  3. 查询用户所在群组信息。将这个表的信息都查询出来select
  4. 发送群聊消息,在这个群的所有成员都可以收到,不在线的成员的消息要存储到离线消息表

客户端首页功能开发

  1. 注册成功,客服端接收到服务器返回的msgid:Reg_MSG_ACK。会打印"register success"
  2. 登陆成功,会打印这个用户的好友列表,群里的好友信息,还有离线消息。

服务器集群

加了nginx ,可以更好处理高并发。有一个服务器宕机,也不影响其他的。

从"单机时代"跨入到了"分布式时代"。不同服务器之间的内存是不共享的。Nginx 把用户 A 分配到了 Server 1,把用户 B 分配到了 Server 2,Server 1 怎么可能拿到 Server 2 内存里的 TCP 连接(userConMap)呢?

引入 基于发布-订阅的redis消息队列

底层就是redis的单Reactor单线程模式,用发发布-订阅 封装。

相关推荐
凭君语未可2 小时前
为什么需要代理?从一个基础问题理解 JDK 静态代理
java·开发语言
luoqice2 小时前
利用flv库读取flv文件时长c程序
c语言·开发语言
NotFound4862 小时前
Go语言中的图形界面开发实战解析:从GUI到WebAssembly
开发语言·golang·wasm
洛水水2 小时前
# 线程池详解:从原理到实现
c++·线程池
北京耐用通信2 小时前
告别通讯掉线!耐达讯自动化Modbus转Profinet网关:工业现场的“定海神针”
服务器·人工智能·网络协议·自动化·信息与通信
Rust研习社2 小时前
Rust Default 特征详解:轻松实现类型默认值
开发语言·后端·rust
思麟呀2 小时前
HTTP的Cookie和Session
linux·网络·c++·网络协议·http
jiayong232 小时前
第 25 课:给学习笔记页加上搜索、标签筛选和 URL 同步
开发语言·前端·javascript·vue.js·学习
小明同学012 小时前
linux进程(下)
linux·服务器·c++