C++聊天集群服务器5

发布时间 2023-12-01 21:26:11作者: 桂洛克船长

一、服务器异常处理函数

​ 这部分主要处理服务器异常退出时,用户的在线状态还是online不会改变,因此需要修改。由于是需要对用户进行操作,因此我们在user表的数据操作类添加重置用户状态函数。

​ 在usermodel.hpp添加后:

#ifndef USERMODEL_
#define USERMODEL_

#include "user.hpp"

//User表的数据操作类
class UserModel
{
public:
    //User表的增加方法
    bool insert(User &user);

    //根据用户号码查询用户信息
    User query(int id);

    //更新用户状态信息
    bool updateState(User user);

    //重置用户信息
    void resetState();
};

#endif

​ 实现:

// 重置用户信息
void UserModel::resetState()
{
    // 1.组装sql语句
    char sql[1024] = "update user set state = 'offline' where state = 'online';";

    MySQL mysql;
    if (mysql.connect())
    {
        mysql.update(sql);
    }
}

​ 在service层添加函数调用model层代码并实现:

image-20231201210959223

image-20231201211012292

​ 然后在主函数注册信号(目前只实现了服务器端ctrl+c)并捕捉:

image-20231201211158396

​ 这样当服务器端按下ctrl+c就会被捕捉然后触发reserHandler函数。

二、添加好友业务函数

​ 在service层添加消息信号,并添加相应的处理函数handler:

image-20231201211430989

image-20231201211444884

​ 在service层添加函数:

image-20231201211609702

​ 实现:

image-20231201211641311

​ 这里就需要一个新的model层,friendmodel实现如下:

image-20231201211737413

​ cpp代码:

#include "friendmodel.hpp"
#include "db.h"


// 添加好友关系
void FriendModel::insert(int userid, int friendid)
{
    //1.组装sql语句
    char sql[1024]={0};
    sprintf(sql,"insert into friend values(%d,%d);",userid,friendid);
    
    MySQL mysql;
    if(mysql.connect())
    {
        mysql.update(sql);
    }
}

// 返回用户好友列表  friendid
vector<User> FriendModel::query(int userid)
{
    //1.组装sql语句
    char sql[1024]={0};
    sprintf(sql,"select a.id,a.name,a.state from user a inner join friend b on b.friendid = a.id where b.userid = %d;",userid);
    
    vector<User> vec;

    MySQL mysql;
    if(mysql.connect())
    {
        MYSQL_RES* res = mysql.query(sql);

        if(res != nullptr)
        {
            MYSQL_ROW row;
            //把userid用户的所有离线消息放入数组,返回
            while((row = mysql_fetch_row(res)) != nullptr)
            {
                User user;
                user.setId(atoi(row[0]));
                user.setName(row[1]);
                user.setState(row[2]);
                vec.push_back(user);
            }

            mysql_free_result(res);
        }
    }
    return vec;
}

三、群组业务开发

​ service层添加函数:

image-20231201211842493

​ 实现:

// 创建群组业务
void ChatService::createGroup(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int userid = js["id"].get<int>();
    string name = js["groupname"];
    string desc = js["groupdesc"];

    // 存储新创建的群组信息
    Group group(-1, name, desc);
    if (_groupModel.createGroup(group))
    {
        // 存储群组创建人信息
        _groupModel.addGroup(userid, group.getId(), "creator");
    }
}
// 加入群组业务
void ChatService::addGroup(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int userid = js["id"].get<int>();
    int groupid = js["groupid"].get<int>();

    _groupModel.addGroup(userid, groupid, "normal");
}

// 群组聊天业务
void ChatService::groupChat(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int userid = js["id"].get<int>();
    int groupid = js["groupid"].get<int>();

    vector<int> useridVec = _groupModel.queryGroupUsers(userid,groupid);

    lock_guard<mutex> lock(_connMutex);
    for(int id : useridVec)
    {
        auto it = _userConnMap.find(id);
        if(it != _userConnMap.end())
        {
            //在线转发消息
            it->second->send(js.dump());
        }
        else
        {
            //离线,存储消息
            _offlineMsgModel.insert(id,js.dump());
        }
    }
}

​ model层增加群定义:

​ group.hpp:

#ifndef GROUP_H
#define GROUP_H

#include "groupuser.hpp"
#include <string>
#include <vector>

using namespace std;

class Group
{
public:
    Group(int id = -1,string name = "",string desc = "")
    {
        this->desc=desc;
        this->name=name;
        this->id=id;
    }

    void setId(int id){this->id=id;};
    void setName(string name){this->name = name;};
    void setDesc(string desc){this->desc = desc;};

    int getId(){return this->id;};
    string getName(){return this->name;};
    string getDesc(){return this->desc;};

    vector<GroupUser> &getUSers(){return this->users;};
private:
    int id;
    string name;
    string desc;    
    vector<GroupUser> users;
};

#endif

​ groupmodel.hpp:

#ifndef GROUPMODEL_H
#define GROUPMODEL_H

#include "group.hpp"
#include <string>
#include <vector>
using namespace std;

class GroupModel
{
public:
    //创建群组
    bool createGroup(Group &group);    
    //加入群组
    void addGroup(int userid,int groupid,string role);
    //查询用户所在群组信息
    vector<Group>  queryGroups(int userid);
    //根据groupid查询群组用户id列表,除userid,主要用来发群聊消息
    vector<int> queryGroupUsers(int userid,int groupid);
};


#endif

​ groupuser继承自user因为只是增加了一个role成员,群组角色:

#ifndef GROUPUSER_H
#define GROUPUSER_H

#include "user.hpp"

class GroupUser : public User
{
public:
    void setRole(string role){this->role = role;};
    string getRole(){return this->role;};

private:
    string role;
};



#endif