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;
}