c++聊天室server端(8)

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 c++聊天室server端(8),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

main函数

#include <signal.h>
#include "ChatServer.hpp"
#include "ChatService.hpp"

using namespace std;

//处理服务器ctrl+c结束后,重置user的状态信息
void reset_handler(int)
{
    ChatService::instance()->reset();
    exit(0);
}

int main(int argc, char **argv)
{
    if (argc < 3)
    {
        cerr << "command invaild example: ./ExeNAME  IpAddress  port" << endl;
        exit(-1);
    }

    //解析IP地址和端口号
    char *ip = argv[1];
    uint16_t port = atoi(argv[2]);
     
    //收到ctrl+c
    signal(SIGINT, reset_handler);

    EventLoop loop;
    InetAddress addr(ip, port);
    ChatServer server(&loop, addr, "ChatServer");

    server.start();
    loop.loop();

    return 0;
}

解析(模型化)

1.头文件的包含
2.int main(int argc,char **agrv)(条件判断)
3.解析argv[1]=ip argc[2]=atoi(port)//a->int
4.sigal的利用(ctrl+c)//单例模式
5、eventloop-》InetAddress-》server-》strat-》loop

ChatServer

hpp

#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 on_connection(const TcpConnectionPtr &);

    ///上报连接相关信息的回调函数
    void on_message(const TcpConnectionPtr &, Buffer *, Timestamp);

private:
    TcpServer server_; //组合的muduo库,实现服务器功能的类对象
    EventLoop *loop_;  //指向事件循环对象的指针
};

#endif

解析

1.#ifndef #define #endif
2.class ChatServer muduo::net::tcpserver server_ eventloop *loop(与muduo挂钩)
3 连接回调on_connect 信息回调 on_message
4 void start chatServer::rall

chatserver.cpp

#include <functional>
#include <string>
#include <iostream>
#include "ChatServer.hpp"
#include "ChatService.hpp"
#include "json.hpp"

using namespace std;
using namespace placeholders;
using json = nlohmann::json;

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

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

    //设置线程数量
    server_.setThreadNum(4);
}

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

//上报连接相关信息的回调函数
void ChatServer::on_connection(const TcpConnectionPtr &conn)
{
    //如果用户断开连接
    if (!conn->connected())
    {
        //处理异常断开
        ChatService::instance()->client_close_exception(conn);
        conn->shutdown();
    }
}

//上报读写时间相关信息的回调函数
void ChatServer::on_message(const TcpConnectionPtr &conn, Buffer *buffer, Timestamp time)
{
    string buf = buffer->retrieveAllAsString();
    cout<<"exute: "<<buf<<endl;
    //数据反序列化
    json js = json::parse(buf);
    //解耦网络和业务模块的代码
    //通过js里面的msgid,绑定msgid的回调函数,获取业务处理器handler
    //已经到前端 js["msgid"].get<int>
    //int msgid()message 标识
    auto msg_handler = ChatService::instance()->get_handler(js["msgid"].get<int>());

    //其实这个msg_handler就是业务处理选项
    msg_handler(conn, js, time);
}

解析

1.初始化绑定 server_  以及loop
2.setconnnectioncallback setmessagecallback setthreadnum
3.on_connection//断开连接 立即单例模式 调用client_close_exception
4.on_message 
先拿-》解析(反序列化)json js=json.prase();
>>通过chatservice::msg_handle 判断login还是regist 
5.遗留问题:为什么用绑定以及单例模式

chatservice

hpp

#ifndef CHATSERVICE_H
#define CHATSERVICE_H

#include <unordered_map>
#include <functional>
#include <mutex>
#include <muduo/net/TcpConnection.h>
#include "json.hpp"
#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;
using namespace placeholders;

using json = nlohmann::json;
using MsgHandler = function<void(const TcpConnectionPtr &conn, json &js, Timestamp time)>;

//聊天服务器业务类,单例模式设计,因为一个就够了。
//映射事件回调用

class ChatService
{
public:
    //获取单例对象
    static ChatService *instance();

    //登录
    void login(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //注册
    void regist(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //一对一聊天业务
    void one_chat(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //添加好友业务
    bool add_friend(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //创建 群组
    bool create_group(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //加入群组
    bool add_group(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //群聊业务
    void group_chat(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //注销业务
    void loginout(const TcpConnectionPtr &conn, json &js, Timestamp time);

    //redis订阅消息触发的回调函数
    void redis_subscribe_message_handler(int channel, string message);

    //获取消息对应的处理器
    MsgHandler get_handler(int msgid);

    //处理客户端异常退出
    void client_close_exception(const TcpConnectionPtr &conn);

    //服务器异常,业务重置
    void reset();

private:
    //注册消息以及对应的回调操作
    ChatService();

private:
    //存储事件触发的回调函数
    unordered_map<int, MsgHandler> msg_handler_map_;

    //存储在线用户的连接情况,便于服务器给用户发消息,注意线程安全
    unordered_map<int, TcpConnectionPtr> user_connection_map_;
    mutex conn_mutex_;

    //redis操作对象
    Redis redis_;

    UserModel user_model_;
    OfflineMessageModel offline_message_model_;
    FriendModel friend_model_;
    GroupModel group_model_;
};

#endif

解析

1(frontend) js['msgid'].get<int> 获得的业务代码
void business(connect,js['migid'].get<int>m,time)//time->log
2.MsgHandeler get_hanler(int msgid)
3.两个异常 client(client_close_exception) server(reset)
4using MsgHandler = function<void(const TcpConnectionPtr &conn, json &js, Timestamp time)>;我们可以使用函数指针来吧一个函数作为参数传递
unordered_map<int, MsgHandler> msg_handler_map_;msgid->business
4、(遗留)
//redis操作对象
    Redis redis_;

    UserModel user_model_;
    OfflineMessageModel offline_message_model_;
    FriendModel friend_model_;
    GroupModel group_model_;

cpp

#include <muduo/base/Logging.h>
#include <vector>
#include <map>
#include <iostream>
#include "ChatService.hpp"
#include "public.hpp"

using namespace muduo;
using namespace std;

//获取单例对象
ChatService *ChatService::instance()
{
    static ChatService service;
    return &service;
}

//注册消息以及对应的回调操作
ChatService::ChatService()
{
    msg_handler_map_.insert({LOGIN_MSG, bind(&ChatService::login, this, _1, _2, _3)});
    msg_handler_map_.insert({LOGINOUT_MSG, bind(&ChatService::loginout, this, _1, _2, _3)});
    msg_handler_map_.insert({REG_MSG, bind(&ChatService::regist, this, _1, _2, _3)});
    msg_handler_map_.insert({ONE_CHAT_MSG, bind(&ChatService::one_chat, this, _1, _2, _3)});
    msg_handler_map_.insert({ADD_FRIEND_MSG, bind(&ChatService::add_friend, this, _1, _2, _3)});
    msg_handler_map_.insert({CREATE_GROUP_MSG, bind(&ChatService::create_group, this, _1, _2, _3)});
    msg_handler_map_.insert({ADD_GROUP_MSG, bind(&ChatService::add_group, this, _1, _2, _3)});
    msg_handler_map_.insert({GROUP_CHAT_MSG, bind(&ChatService::group_chat, this, _1, _2, _3)});

    if (redis_.connect())
    {
        redis_.init_notify_handler(bind(&ChatService::redis_subscribe_message_handler, this, _1, _2));
    }
}

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

//登录
void ChatService::login(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int id = js["id"].get<int>();
    string password = js["password"];

    User user = user_model_.query(id);
    //cout << "js:" << js << endl;

    if (user.get_id() == id && user.get_password() == password)
    {
        //用户在线
        if (user.get_state() == "online")
        {
            //用户不存在
            json response;
            response["msgid"] = LOGIN_MSG_ACK;
            response["errno"] = 2;
            response["errmsg"] = "id is online";

            conn->send(response.dump());
        }
        else
        {
            //登陆成功
            {
                //记录用户连接信息,注意线程安全
                lock_guard<mutex> lock(conn_mutex_);
                user_connection_map_.insert({id, conn});
            }

            //订阅Redis
            redis_.subscribe(id);

            //更新用户状态信息
            user.set_state("online");
            user_model_.update_state(user);

            json response;
            response["msgid"] = LOGIN_MSG_ACK;
            response["errno"] = 0;
            response["id"] = user.get_id();
            response["name"] = user.get_name();

            //查询用户是否有离线消息
            vector<string> vec = offline_message_model_.query(id);
            //增加离线消息
            if (!vec.empty())
            {
                response["offlinemsg"] = vec;
                //读取完后删除消息
                offline_message_model_.remove(id);
            }

            //查询该用户的好友信息并返回
            vector<User> user_vec = friend_model_.query(id);
            if (!user_vec.empty())
            {
                vector<string> friend_vec;
                for (User &user : user_vec)
                {
                    json js;
                    js["id"] = user.get_id();
                    js["name"] = user.get_name();
                    js["state"] = user.get_state();
                    friend_vec.push_back(js.dump());
                }
                response["friends"] = friend_vec;
            }

            //查询该用户的群组信息并返回
            vector<Group> group_vec = group_model_.query_group(id);
            if (!group_vec.empty())
            {
                // group:[{groupid:[xxx, xxx, xxx, xxx]}]
                vector<string> groupV;
                for (Group &group : group_vec)
                {
                    json grpjson;
                    grpjson["id"] = group.get_id();
                    grpjson["groupname"] = group.get_name();
                    grpjson["groupdesc"] = group.get_desc();

                    vector<string> userV;
                    for (GroupUser &user : group.get_User())
                    {
                        json js;
                        js["id"] = user.get_id();
                        js["name"] = user.get_name();
                        js["state"] = user.get_state();
                        js["role"] = user.get_role();
                        userV.push_back(js.dump());
                    }
                    grpjson["users"] = userV;

                    groupV.push_back(grpjson.dump());
                }

                response["groups"] = groupV;
            }

            conn->send(response.dump());
        }
    }
    else
    {
        //用户不存在或密码错误
        json response;
        response["msgid"] = LOGIN_MSG_ACK;
        response["errno"] = 1;
        response["errmsg"] = "id or password error";

        conn->send(response.dump());
    }
}

//注册
void ChatService::regist(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    string name = js["name"];
    string password = js["password"];

    User user;
    user.set_name(name);
    user.set_password(password);

    bool state = user_model_.insert(user);
    if (state)
    {
        //注册成功
        json response;
        response["msgid"] = REG_MSG_ACK;
        response["errno"] = 0;
        response["id"] = user.get_id();

        conn->send(response.dump());
    }
    else
    {
        //注册失败
        json response;
        response["msgid"] = REG_MSG_ACK;
        response["errno"] = 1;

        conn->send(response.dump());
    }
}

//处理客户端异常退出
void ChatService::client_close_exception(const TcpConnectionPtr &conn)
{
    //1.删除user_map    2.用户改为offline   3.线程安全
    User user;
    {
        lock_guard<mutex> lock(conn_mutex_);
        for (auto it = user_connection_map_.begin(); it != user_connection_map_.end(); it++)
        {
            if (it->second == conn)
            {
                user.set_id(it->first);
                user_connection_map_.erase(it);
                break;
            }
        }
    }

    //取消订阅
    redis_.unsubscribe(user.get_id());

    if (user.get_id() != -1)
    {
        user.set_state("offline");
        user_model_.update_state(user);
    }
}

//一对一聊天业务
void ChatService::one_chat(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int receive_id = js["to"].get<int>();

    {
        lock_guard<mutex> lock(conn_mutex_);
        auto it = user_connection_map_.find(receive_id);
        if (it != user_connection_map_.end())
        {
            //用户在线,转发消息给receive用户
            it->second->send(js.dump());
            return;
        }
    }

    //用户在其他主机,publish消息到redis
    User user = user_model_.query(receive_id);
    if (user.get_state() == "online")
    {
        redis_.publish(receive_id, js.dump());
        return;
    }

    //  用户不在线,存储离线消息
    offline_message_model_.insert(receive_id, js.dump());
}

//添加好友业务
bool ChatService::add_friend(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int user_id = js["id"].get<int>();
    int friend_id = js["friendid"].get<int>();

    //存储好友信息
    friend_model_.insert(user_id, friend_id);
}

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

    //创建群组信息
    Group group(-1, name, desc);
    if (group_model_.create_group(group))
    {
        //存储群主信息
        if (group_model_.add_group(user_id, group.get_id(), "creator"))
        {
            return true;
        }
    }
    return false;
}

//加入群组
bool ChatService::add_group(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int user_id = js["id"].get<int>();
    int group_id = js["groupid"].get<int>();
    if (group_model_.add_group(user_id, group_id, "normal"))
    {
        return true;
    }
    return false;
}

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

    vector<int> userid_vec = group_model_.query_group_users(user_id, group_id);

    lock_guard<mutex> lock(conn_mutex_);
    for (int id : userid_vec)
    {
        auto it = user_connection_map_.find(id);
        if (it != user_connection_map_.end())
        {
            //转发群消息
            it->second->send(js.dump());
        }
        else
        {
            //用户在其他服务器登录
            User user = user_model_.query(id);
            if (user.get_state() == "online")
            {
                redis_.publish(id, js.dump());
            }
            else
            {
                //转储离线消息
                offline_message_model_.insert(id, js.dump());
            }
        }
    }
}

//服务器异常,业务重置
void ChatService::reset()
{
    //把online用户设置为offline
    user_model_.reset_state();
}

//注销业务
void ChatService::loginout(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
    int user_id = js["id"].get<int>();

    {
        lock_guard<mutex> lock(conn_mutex_);
        auto it = user_connection_map_.find(user_id);
        if (it != user_connection_map_.end())
        {
            user_connection_map_.erase(it);
        }
    }

    //取消Redis订阅
    redis_.unsubscribe(user_id);

    // 更新用户的状态信息
    User user(user_id, "", "", "offline");
    user_model_.update_state(user);
}

//redis订阅消息触发的回调函数,这里channel其实就是id
void ChatService::redis_subscribe_message_handler(int channel, string message)
{
    //用户在线
    lock_guard<mutex> lock(conn_mutex_);
    auto it = user_connection_map_.find(channel);
    if (it != user_connection_map_.end())
    {
        it->second->send(message);
        return;
    }

    //转储离线
    offline_message_model_.insert(channel, message);
}

##解析

1.先不管redis部分(后面解读)
2.return [=] 返回一个匿名函数 (日志)
否则返回一个函数pointer

3.login:
逻辑:(后端js 直接)
1.判断id是在mysql(user)
2、有:判断是否在线 online
 online:json.dump(dict->str)
 offline:
 log success 上锁 hash thread
 offline:
 (1)增加消息 删除消息 
 (2)返回user以及group groupuser(vector)
 (3)reponse封装三个vector
3.否 就是 

4.regist(easy)
注意 user password 是frontend输入
所以我们得js封装一下

5.客户端
上锁 再看 再去 erase
redis unsub 修改state

6.one_chat 
online://转发消息给receive用户
offline:store

7.create_group 
注意:存储群主信息


model(model可以看成server->mysql的映射)

Group User GroupUser

#ifndef USER_H
#define USER_H

#include <string>
using namespace std;

class User
{
public:
    User(int id = -1, string name = "", string password = "", string state = "offline")
    {
        id_ = id;
        name_ = name;
        password_ = password;
        state_ = state;
    }

    void set_id(int id)
    {
        id_ = id;
    }

    void set_name(string name)
    {
        name_ = name;
    }

    void set_password(string password)
    {
        password_ = password;
    }

    void set_state(string state)
    {
        state_ = state;
    }

    int get_id()
    {
        return id_;
    }

    string get_name()
    {
        return name_;
    }

    string get_password()
    {
        return password_;
    }

    string get_state()
    {
        return state_;
    }

private:
    int id_;
    string name_;
    string password_;
    string state_;
};
#endif

#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 = "")
    {
        id_ = id;
        name_ = name;
        desc_ = desc;
    }

    void set_id(int id)
    {
        id_ = id;
    }

    void set_name(string name)
    {
        name_ = name;
    }

    void set_desc(string desc)
    {
        desc_ = desc;
    }

    int get_id()
    {
        return id_;
    }

    string get_name()
    {
        return name_;
    }

    string get_desc()
    {
        return desc_;
    }

    vector<GroupUser> &get_User()
    {
        return user_;
    }

private:
    int id_;
    string name_;
    string desc_;
    vector<GroupUser> user_;
};

#endif

#ifndef GROUPUSER_H
#define GROUPUSER_H

#include "User.hpp"

class GroupUser : public User
{
public:
    void set_role(string role)
    {
        role_ = role;
    }

    string get_role()
    {
        return role_;
    }

private:
    string role_;
};
#endif

解析

groupuser 继承 user

friendModel

#ifndef FRIENDMODEL_H
#define FRIENDMODEL_H

#include <vector>
#include "User.hpp"

using namespace std;

//维护好友信息的结构方法
class FriendModel
{
public:
    //添加好友关系
    bool insert(int user_id, int friend_id);

    //返回用户好友列表
    vector<User> query(int user_id);
};#include "FriendModel.hpp"
#include "MySQL.hpp"

//添加好友关系
bool FriendModel::insert(int user_id, int friend_id)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "insert into Friend values(%d,%d);", user_id, friend_id);
    //cout << sql << endl;

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

//返回用户好友列表
vector<User> FriendModel::query(int user_id)
{
    //组装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;", user_id);
    //cout << sql << endl;

    vector<User> vec;
    MySQL mysql;
    if (mysql.connet())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                User user;
                user.set_id(atoi(row[0]));
                user.set_name(row[1]);
                user.set_state(row[2]);
                vec.push_back(user);
            }
            //释放资源,否则内存不断泄露
            mysql_free_result(res);
        }
    }
    return vec;
}
#endif






解析

add_friend:mysql的insert“insert into Friend values(%d,%d)“
return_vec:"select  a.id,a.name,a.state from User a inner join Friend b on b.friendid = a.id  where b.userid=%d;"//user friendr 联系一起

GROUP

ifndef GROUPMODEL_H
#define GROUPMODEL_H

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

using namespace std;

class GroupModel
{
public:
    //创建群组
    bool create_group(Group &group);

    //加入群组
    bool add_group(int user_id, int group_id, string role);

    //查询用户所在群组信息
    vector<Group> query_group(int user_id);

    //根据指定的groupid查询群组用户id列表,除userid自己,给该群用户群发消息
    vector<int> query_group_users(int user_id, int group_id);
};

#endif

#include "GroupModel.hpp"
#include "MySQL.hpp"
#include<iostream>
using namespace std;

//创建群组
bool GroupModel::create_group(Group &group)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "insert into AllGroup(groupname,groupdesc) values('%s','%s');", group.get_name().c_str(), group.get_desc().c_str());
    //cout << sql << endl;

    MySQL mysql;
    if (mysql.connet())
    {
        if (mysql.update(sql))
        {
            group.set_id(mysql_insert_id(mysql.get_connection()));
            return true;
        }
    }
    return false;
}

//加入群组
bool GroupModel::add_group(int user_id, int group_id, string role)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "insert into GroupUser values(%d,%d,'%s');", group_id, user_id, role.c_str());
    cout << sql << endl;

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

//查询用户所在群组信息
vector<Group> GroupModel::query_group(int user_id)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "select  a.id,a.groupname,a.groupdesc from AllGroup a inner join GroupUser b on b.groupid=a.id  where b.userid=%d;", user_id);
    //cout << sql << endl;

    vector<Group> group_vec;
    MySQL mysql;
    if (mysql.connet())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                Group group;
                group.set_id(atoi(row[0]));
                group.set_name(row[1]);
                group.set_desc(row[2]);
                group_vec.push_back(group);
            }
            //释放资源,否则内存不断泄露
            mysql_free_result(res);
        }
    }

    //查询群组所有群员的信息
    for (Group &temp : group_vec)
    {
        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;", temp.get_id());

        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                GroupUser group_user;
                group_user.set_id(atoi(row[0]));
                group_user.set_name(row[1]);
                group_user.set_state(row[2]);
                group_user.set_role(row[3]);
                temp.get_User().push_back(group_user);
            }
            //释放资源,否则内存不断泄露
            mysql_free_result(res);
        }
        return group_vec;
    }
}

//根据指定的groupid查询群组用户id列表,除userid自己,给该群用户群发消息
vector<int> GroupModel::query_group_users(int user_id, int group_id)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "select userid  from GroupUser where groupid=%d and userid != %d;", group_id, user_id);
    //cout << sql << endl;

    vector<int> id_vec;
    MySQL mysql;
    if (mysql.connet())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res)) != nullptr)
            {
                id_vec.push_back(atoi(row[0]));
            }
            //释放资源,否则内存不断泄露
            mysql_free_result(res);
        }
    }
    retur#ifndef USERMODEL_H
#define USERMODEL_H

#include "User.hpp"

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

    //根据ID查询user信息
    User query(int id);

    //更新状态操作
    bool update_state(User user);

    //重置用户状态信息
    bool reset_state();
};
#endifn id_vec;
}


USER

#ifndef USERMODEL_H
#define USERMODEL_H

#include "User.hpp"

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

    //根据ID查询user信息
    User query(int id);

    //更新状态操作
    bool update_state(User user);

    //重置用户状态信息
    bool reset_state();
};
#endif




#include <iostream>
#include "UserModel.hpp"
#include "MySQL.hpp"

using namespace std;

//增加User
bool UserModel::insert(User &user)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "insert into User(name,password,state) values('%s','%s','%s')",
            user.get_name().c_str(), user.get_password().c_str(), user.get_state().c_str());

    MySQL mysql;
    if (mysql.connet())
    {
        if (mysql.update(sql))
        {
            //获取自增的用户ID
            user.set_id(mysql_insert_id(mysql.get_connection()));
            return true;
        }
    }
    return false;
}

//根据ID查询user信息,失败返回一个默认构造User,id = -1
User UserModel::query(int id)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "select * from User where id=%d", id);

    MySQL mysql;
    if (mysql.connet())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row = mysql_fetch_row(res);
            if (row != nullptr)
            {
                User user;
                user.set_id(atoi(row[0]));
                user.set_name(row[1]);
                user.set_password(row[2]);
                user.set_state(row[3]);

                //释放资源,否则内存不断泄露
                mysql_free_result(res);

                return user;
            }
        }
    }
    return User();
}

//更新状态操作
bool UserModel::update_state(User user)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "update User set state='%s'  where id=%d;", user.get_state().c_str(), user.get_id());
    //cout << sql << endl;

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

//重置用户状态信息
bool UserModel::reset_state()
{
     //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "update User set state='offline'  where state='online';");
    //cout << sql << endl;

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


offlinemessage

#ifndef OFFLINEMESSAGEMODEL_H
#define OFFLINEMESSAGEMODEL_H

#include <string>
#include <vector>

using namespace std;

//关于offlinemessage表的操作
class OfflineMessageModel
{
public:
    //存储用户的离线消息
    bool insert(int id, string msg);

    //删除用户的离线消息
    bool remove(int id);

    //查询用户的聊天消息
    vector<string> query(int id);
};
#endif

#include <iostream>
#include "UserModel.hpp"
#include "MySQL.hpp"

using namespace std;

//增加User
bool UserModel::insert(User &user)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "insert into User(name,password,state) values('%s','%s','%s')",
            user.get_name().c_str(), user.get_password().c_str(), user.get_state().c_str());

    MySQL mysql;
    if (mysql.connet())
    {
        if (mysql.update(sql))
        {
            //获取自增的a用户ID
            user.set_id(mysql_insert_id(mysql.get_connection()));
            return true;
        }
    }
    return false;
}

//根据ID查询user信息,失败返回一个默认构造User,id = -1
User UserModel::query(int id)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "select * from User where id=%d", id);

    MySQL mysql;
    if (mysql.connet())
    {
        MYSQL_RES *res = mysql.query(sql);
        if (res != nullptr)
        {
            MYSQL_ROW row = mysql_fetch_row(res);
            if (row != nullptr)
            {
                User user;
                user.set_id(atoi(row[0]));
                user.set_name(row[1]);
                user.set_password(row[2]);
                user.set_state(row[3]);

                //释放资源,否则内存不断泄露
                mysql_free_result(res);

                return user;
            }
        }
    }
    return User();
}

//更新状态操作
bool UserModel::update_state(User user)
{
    //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "update User set state='%s'  where id=%d;", user.get_state().c_str(), user.get_id());
    //cout << sql << endl;

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

//重置用户状态信息
bool UserModel::reset_state()
{
     //组装SQL语句
    char sql[1024] = {0};
    sprintf(sql, "update User set state='offline'  where state='online';");
    //cout << sql << endl;

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



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/129724.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!