C++项目——集群聊天服务器项目(十二)群组业务

本文介绍了聊天服务器中群组业务的实现。包括数据库表及对应类的设计,如群组表、群组用户表等;详细阐述了创建群组、加入群组、群组聊天等业务的步骤和代码实现;还验证了群聊业务的功能。此外,给出了项目的整体流程,涉及环境搭建、库介绍等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

聊天服务器中,不仅要实现不同用户之间聊天,还要实现群聊。

今天我们就一起来实现一下群组相关的业务吧~

一、群组业务介绍

1.1 数据库表及对应类

底层数据库中,除了有用户表User、好友表Friend、离线消息表OfflineMessage表,还有群组及群组用户表

群组表Allgroup存放所有群组的群号,群组名及群组描述

群组用户表GroupUser存放群号及对应群内组员编号和群内组员角色

为了操作群组表,我们同User类对象一致,定义Group类

在include/server/model创建group.hpp头文件,定义Group类

#ifndef GROUP_H
#define GROUP_H

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

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

    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;                  // 群组id
    string name;             // 群组名称
    string desc;             // 群组描述
    vector<GroupUser> users; // 群组用户数组
};

#endif

其中GroupUser类继承自User类(毕竟群组成员也是用户),users代表对应群组的群组成员列表

在include/server/model创建groupuser.hpp头文件,定义GroupUser类

#ifndef GROUPUSER_H
#define GROUPUSER_H

#include "user.hpp"

// 群组用户,多了一个role角色信息,从User类直接继承,复用User的其它信息
class GroupUser : public User
{
public:
    void setRole(string role) { this->role = role; }
    string getRole() { return this->role; }

private:
    string role;            //群组用户角色,分为creator 与 normal
};

#endif

在User类基础上,GroupUser多了一个属性,名为群组角色,分为创建者creator与普通群成员

在include/server/model创建groupmodel.hpp头文件,定义GroupModel类操作群组

#ifndef GROUPMODEL_H
#define GROUPMODEL_H

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

// 维护群组信息的操作接口方法
class GroupModel
{
public:
    // 创建群组
    bool createGroup(Group &group);
    // 加入群组
    bool addGroup(int userid, int groupid, string role);
    // 查询用户所在群组信息
    vector<Group> queryGroups(int userid);
    //群聊,除用户userid自身
    vector<int> queryGroupUsers(int userid, int groupid);
};

#endif

其中有创建群组,加入群组,查询用户所在群组信息及群聊函数

在src/server/model创建groupmodel.cpp源文件,实现GroupModel类

类似于向数据库中插入用户,这里向数据库中插入群组,即创建群组

// 创建群组
bool GroupModel::createGroup(Group &group)
{
    char sql[1024] = {0};
    sprintf(sql, "insert into allgroup(groupname, groupdesc) values('%s', '%s')",
            group.getName().c_str(), group.getDesc().c_str()); // 向群组表中插入群组名和群组描述信息

    MySQL mysql;
    if (mysql.connect())
    {
        if (mysql.update(sql))
        {
            group.setId(mysql_insert_id(mysql.getConnection())); // 数据库自动生成id号,设置群组id
            return true;
        }
    }

    return false;
}

群组创建好后,成员欲加入群组,实现函数

// 加入群组
bool GroupModel::addGroup(int userid, int groupid, string role)
{
    char sql[1024] = {0};
    sprintf(sql, "insert into groupuser values(%d, %d, '%s')", groupid, userid, role.c_str());

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

一个用户可以属于多个群组,一个群组同样包含多个用户,是多对多的关系

因此,我们要

1. 先根据userid在groupuser表中查询出该用户所属的群组信息

 2. 再根据群组信息,查询属于该群组的所有用户的userid,并且和user表进行多表联合查询,查出用户的详细信息,反馈至对应群组的用户表users中

// 查询用户所在群组信息
vector<Group> GroupModel::queryGroups(int userid)
{
    /*
    1. 先根据userid在groupuser表中查询出该用户所属的群组信息
    2. 再根据群组信息,查询属于该群组的所有用户的userid,并且和user表进行多表联合查询,查出用户的详细信息
    */
    char sql[1024] = {0};
    sprintf(sql, "select a.id,a.groupname,a.groupdesc from allgroup a inner join \
         groupuser b on a.id = b.groupid where b.userid=%d",
            userid); // 多表联合查询,获取该用户所属的所有群组信息

    vector<Group> groupVec; // 定义数组存放群组对象

    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)
            {
                Group group;
                group.setId(atoi(row[0]));
                group.setName(row[1]);
                group.setDesc(row[2]);
                groupVec.push_back(group);
            }
            mysql_free_result(res);
        }
    }

    // 查询群组的用户信息
    for (Group &group : groupVec)
    {
        sprintf(sql, "select a.id,a.name,a.state,b.grouprole from user a \
            inner join groupuser b on b.userid = a.id where b.groupid=%d",
                group.getId()); // 多表联合查询,获取不同群组中所有用户信息,并添加至对应群组的用户数组中

        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                GroupUser user;
                user.setId(atoi(row[0]));
                user.setName(row[1]);
                user.setState(row[2]);
                user.setRole(row[3]);
                group.getUsers().push_back(user); // 调用getUsers函数获取群组用户数组对象
            }
            mysql_free_result(res);
        }
    }
    return groupVec;
}

群组聊天类似于点对点聊天,点对点向指定id用户发送消息即可,离线存储离线消息表中

群组聊天发送给所属群内所有用户,除自身userid之外,类似操作如下

// 群聊,除用户userid自身
vector<int> GroupModel::queryGroupUsers(int userid, int groupid)
{
    char sql[1024] = {0};
    sprintf(sql, "select userid from groupuser where groupid = %d and userid != %d", groupid, userid); // 获取群组中除自身userid之外的所有用户id

    vector<int> idVec; // 定义数组存放群组用户id
    MySQL mysql;
    if (mysql.connect())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                idVec.push_back(atoi(row[0]));
            }
            mysql_free_result(res);
        }
    }
    return idVec;
}

因此,groupmodel.cpp源文件如下:

#include "groupmodel.hpp"
#include "db.hpp"
#include <vector>

// 创建群组
bool GroupModel::createGroup(Group &group)
{
    char sql[1024] = {0};
    sprintf(sql, "insert into allgroup(groupname, groupdesc) values('%s', '%s')",
            group.getName().c_str(), group.getDesc().c_str()); // 向群组表中插入群组名和群组描述信息

    MySQL mysql;
    if (mysql.connect())
    {
        if (mysql.update(sql))
        {
            group.setId(mysql_insert_id(mysql.getConnection())); // 数据库自动生成id号,设置群组id
            return true;
        }
    }

    return false;
}

// 加入群组
bool GroupModel::addGroup(int userid, int groupid, string role)
{
    char sql[1024] = {0};
    sprintf(sql, "insert into groupuser values(%d, %d, '%s')", groupid, userid, role.c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值