C++聊天集群服务器5
一、服务器异常处理函数
这部分主要处理服务器异常退出时,用户的在线状态还是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层代码并实现:
然后在主函数注册信号(目前只实现了服务器端ctrl+c)并捕捉:
这样当服务器端按下ctrl+c就会被捕捉然后触发reserHandler函数。
二、添加好友业务函数
在service层添加消息信号,并添加相应的处理函数handler:
在service层添加函数:
实现:
这里就需要一个新的model层,friendmodel实现如下:
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层添加函数:
实现:
// 创建群组业务
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