[集群聊天服务器]----(七)业务模块之一对一聊天、添加好友函数、好友类以及离线消息类

本文主要是介绍[集群聊天服务器]----(七)业务模块之一对一聊天、添加好友函数、好友类以及离线消息类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接着[集群聊天服务器]----(六)业务模块之用户注册、登录、退出以及客户端异常退出函数中对于业务模块的用户注册、登录、退出以及客户端异常退出函数的剖析,现在我们对点对点聊天以及添加好友的实现进行剖析。

点对点聊天

当客户端输入msgid=ONE_CHAT_MSG时,ChatService::ChatService()中会回调ChatService::oneChat()函数进行处理

void ChatService::oneChat(const TcpConnectionPtr &conn, json &js, Timestamp time)
{int toid = js["toid"].get<int>(); // 对方的id{//在一台主机上lock_guard<mutex> lock(_connMutex); // 线程安全auto it = _userConnMap.find(toid);if (it != _userConnMap.end()){// toid 在线 转发消息 服务器主动推送消息给toid用户it->second->send(js.dump());return;}}// 查询toid是否在线User user = _userModel.query(toid);//在另一台电脑上if (user.getState() == "online"){_redis.publish(toid, js.dump());return;}// toid 不在线 存储离线消息_offlineMsgModel.insert(toid, js.dump());
}
  • 通过 JSON 对象反序列结果,寻找toid对应的值,找到用户想要对话的用户,并在_userConnMap中进行查找是否有此对象;
  • 如果用户在一台主机并且处于在线状态,就发送想要发送的消息;
  • 如果不在同一台主机,根据toid调用_userModel在user表中进行查看对方是否在线,如果在线就通过redis发布消息
  • 不在线就存储其离线消息

添加好友

当客户端输入msgid=ADD_FRIEND_MSG时,ChatService::ChatService()中会回调ChatService::addFriend()函数进行处理

void ChatService::addFriend(const TcpConnectionPtr &conn, json &js, Timestamp time)
{int userid = js["id"].get<int>();int friendid = js["friendid"].get<int>();// 存储好友信息_friendModel.insert(userid, friendid);
}
  • 根据客户端获取的用户id以及想要添加的好友id,在好友表中进行存储;

好友消息FriendModel

//添加好友关系
void insert(int userid, int friendid);//返回用户好友列表 friendid=>friendname id
vector<User> query(int userid);

添加好友关系

void FriendModel::insert(int userid, int friendid)
{char sql[1024] = {0};sprintf(sql, "insert into friend values(%d,%d)", userid, friendid);MySQL mysql;// 连接数据库if (mysql.connect()){// 更新数据库语句mysql.update(sql);}
}
  • 组装sql语句,根据用户id以及好友id( userid, friendid),在friend表中进行更改

返回用户好友列表

vector<User> FriendModel::query(int userid)
{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 ;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;}}return vec;}
  • 组装sql语句,根据userid在user 和 friend表进行联合查询好友的id name state
  • 根据sql语句,调用MySQL::query()语句进行查找好友,然后调用mysql_fetch_row()函数,查找对应的行,rowMYSQL_ROW类型,可以根据下标找到对应的值,并把id name state放入vec中返回
  • 注意释放资源

离线消息类OfflineMsgModel

//存储用户的离线消息
void insert(int userid, string msg);//删除用户的离线消息
void remove(int userid);//查询用户的离线消息
vector<string> query(int userid);

存储用户的离线消息

void OfflineMsgModel::insert(int userid, string msg)
{char sql[1024] = {0};sprintf(sql, "insert into offlinemessage values(%d,'%s')", userid, msg.c_str());MySQL mysql;// 连接数据库if (mysql.connect()){// 更新数据库语句mysql.update(sql);}
}
  • 组装sql语句,根据userid像offlinemessage表中添加离线消息msg
  • 连接数据库,并进行更新

删除用户的离线消息

在用户登录以后,需要显示离线消息,并删除用户的离线消息表

void OfflineMsgModel::remove(int userid)
{char sql[1024] = {0};sprintf(sql, "delete from offlinemessage where userid=%d", userid);MySQL mysql;// 连接数据库if (mysql.connect()){// 更新数据库语句mysql.update(sql);}
}
  • 组装sql语句,根据userid在offlinemessage表中删除相关消息
  • 连接数据库,并进行更新

查询用户的离线消息

vector<string> OfflineMsgModel::query(int userid)
{char sql[1024] = {0};sprintf(sql, "select message from offlinemessage where userid = %d", userid);vector<string> vec;MySQL mysql;// 连接数据库if (mysql.connect()){// 更新数据库语句MYSQL_RES *res = mysql.query(sql); // 指针 内部动态内存开辟 需要释放资源if (res != nullptr){// 获取行 根据主键查//把userid用户的所有离线消息放入vec中返回MYSQL_ROW row ;while((row = mysql_fetch_row(res)) != nullptr) {vec.push_back(row[0]);}mysql_free_result(res);return vec;}}return vec;
}
  • 组装sql语句,根据userid在offlinemessage表查找离线消息;
  • 根据sql语句,调用MySQL::query()语句进行查找好友,然后调用mysql_fetch_row()函数,查找对应的行,rowMYSQL_ROW类型,可以根据下标找到对应的值,并把离线消息放入vec中返回
  • 注意释放资源

好了~ 关于业务模块的一对一聊天、添加好友函数、好友类以及离线消息类的剖析就到此结束了,下一节我们将对群组进行剖析,下一节见~~

这篇关于[集群聊天服务器]----(七)业务模块之一对一聊天、添加好友函数、好友类以及离线消息类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1004129

相关文章

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

Python中的getopt模块用法小结

《Python中的getopt模块用法小结》getopt.getopt()函数是Python中用于解析命令行参数的标准库函数,该函数可以从命令行中提取选项和参数,并对它们进行处理,本文详细介绍了Pyt... 目录getopt模块介绍getopt.getopt函数的介绍getopt模块的常用用法getopt模

Redis消息队列实现异步秒杀功能

《Redis消息队列实现异步秒杀功能》在高并发场景下,为了提高秒杀业务的性能,可将部分工作交给Redis处理,并通过异步方式执行,Redis提供了多种数据结构来实现消息队列,总结三种,本文详细介绍Re... 目录1 Redis消息队列1.1 List 结构1.2 Pub/Sub 模式1.3 Stream 结

springboot上传zip包并解压至服务器nginx目录方式

《springboot上传zip包并解压至服务器nginx目录方式》:本文主要介绍springboot上传zip包并解压至服务器nginx目录方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录springboot上传zip包并解压至服务器nginx目录1.首先需要引入zip相关jar包2.然

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI