当前位置: 首页 > news >正文

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

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

点对点聊天

当客户端输入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中返回
  • 注意释放资源

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

相关文章:

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

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

java中使用jedis连接redis

4.java中使用jedis连接redis...

【多线程开发 2】从代码到实战TransmittableThreadLocal

【多线程开发 2】从代码到实战TransmittableThreadLocal 本文将从以下几个点讲解TransmittableThreadLocal(为了方便写以下简称ttl)&#xff1a; 前身 是什么&#xff1f; 可以用来做什么&#xff1f; 源码原理 实战 前身 ThreadLocal 要了解ttl就要先了解Java自带的类…...

【车载以太网测试从入门到精通】——SOME/IP协议测试

系列文章目录 【车载以太网测试从入门到精通】系列文章目录汇总 文章目录 系列文章目录前言一、SOME/IP时间参数1.INITIAL_DELAY时间2.REPETITIONS_MAX次数3.REPETITIONS_BASE_DELAY时间4.CYCLIC_OFFER_DELAY时间5.TIME_TO_LIVE时间6.SUBSCRIBE_RETRY_DELAY时间二、SOME/IP服务…...

作业39 sqrt应用

目录 判断完全平方数 题目描述 输出所有因数 题目描述 因子求和 题目描述 判断素数 题目描述 判断完全平方数 题目描述 输入一个整数&#xff0c;判断他是否是完全平方数&#xff0c;如果是&#xff0c;输出yes&#xff0c;否则输出no 样例 样例…...

springboot 实现跨域的几种方式

1、跨域的原因&#xff1a; 由于同源策略(Same Origin Policy)的限制,浏览器不允许跨域请求。同源策略规定,A网页设置的Cookie、LocalStorage和IndexDB无法被同源以外的网页读取。 2、原因&#xff1a; 1&#xff09;浏览器的同源策略(Same Origin Policy)限制了跨域请求。主要…...

springmvc Web上下文初始化

Web上下文初始化 web上下文与SerlvetContext的生命周期应该是相同的&#xff0c;springmvc中的web上下文初始化是由ContextLoaderListener来启动的 web上下文初始化流程 在web.xml中配置ContextLoaderListener <listener> <listener-class>org.springframework.…...

Verilog实战学习到RiscV - 2 : wire 和 reg 的区别

Verilog: wire 和 reg 的区别 1 引言 看Verilog例子过程中&#xff0c;总是分不清 wire 和 reg 的区别。这篇文章把两者放在一起总结一下&#xff0c;并且对比何时使用它们。 1.1 wire &#xff1a;组合逻辑 wire 是 Verilog 设计中的简单导线&#xff08;或任意宽度的总线…...

OpenGL给定直线起点和终点不同的颜色,使用中点Bresenham画线

用鼠标左键按下确定直线起点&#xff0c;鼠标左键抬起确定直线终点。放一部分代码。 // 中点Bresenham算法.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <GL/glut.h> #include <iostream> #include <cmath>int windowWidt…...

IT行业的现状与未来发展趋势:从云计算到量子计算的技术变革

随着技术的不断进步&#xff0c;IT行业已经成为推动全球经济和社会发展的关键力量。从云计算、大数据、人工智能到物联网、5G通信和区块链&#xff0c;这些技术正在重塑我们的生活和工作方式。本文将深入探讨当前IT行业的现状&#xff0c;并展望未来发展趋势&#xff0c;旨在为…...

电脑远程控制另一台电脑怎么弄?

可以远程控制另一台电脑吗&#xff1f; “你好&#xff0c;我对远程访问技术不太了解。现在&#xff0c;我希望我的朋友可以远程控制我的Windows 10电脑&#xff0c;以便她能帮我解决一些问题。请问&#xff0c;有没有免费的方法可以实现这种远程控制&#xff1f;我该如何操作…...

软件设计师备考 | 案例专题之面向对象设计 概念与例题

相关概念 关系 依赖&#xff1a;一个事物的语义依赖于另一个事物的语义的变化而变化 关联&#xff1a;一种结构关系&#xff0c;描述了一组链&#xff0c;链是对象之间的连接。分为组合和聚合&#xff0c;都是部分和整体的关系&#xff0c;其中组合事物之间关系更强。两个类之…...

UniApp 2.0可视化开发工具:引领前端开发新纪元

一、引言 在移动互联网迅猛发展的今天&#xff0c;移动应用开发已经成为前端开发的重要方向之一。为了简化移动应用开发流程&#xff0c;提高开发效率&#xff0c;各大开发平台不断推出新的工具和框架。UniApp作为一款跨平台的移动应用开发框架&#xff0c;自诞生以来就备受开…...

前端调用浏览器录音功能且生成文件(vue)

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; 首先在页面中给两个按钮&#xff0c;分别是“开始录音”&#xff0c;“结束录音”。以及录音成功后生成一个下载语音的链接。 1. 先看页面展示 <template><div><button click"startRecording…...

「大数据」Kappa架构

Kappa架构是一种处理大数据的架构&#xff0c;它作为Lambda架构的替代方案出现。Kappa架构的核心思想是简化数据处理流程&#xff0c;通过使用单一的流处理层来同时处理实时和批量数据&#xff0c;从而避免了Lambda架构中需要维护两套系统&#xff08;批处理层和速度层&#xf…...

详细分析Element Plus中的ElMessageBox弹窗用法(附Demo及模版)

目录 前言1. 基本知识2. Demo3. 实战4. 模版 前言 由于需要在登录时&#xff0c;附上一些用户说明书的弹窗 对于ElMessageBox的基本知识详细了解 可通过官网了解基本的语法知识ElMessageBox官网基本知识 1. 基本知识 Element Plus 是一个基于 Vue 3 的组件库&#xff0c;其中…...

Python自动化工具(桌面自动化、Web自动化、游戏辅助)

工具介绍 连点工具是一款可以模拟键鼠后台操作的连点器工具。支持鼠标连点、键鼠脚本录制&#xff0c;支持辅助您实现办公自动化以及辅助游戏操作。功能简洁易用&#xff0c;非常方便操作。连点工具让您在在玩游戏、网购抢购的时候全自动点击鼠标&#xff01;主要功能有&#…...

opencv进阶 ——(五)图像处理之马赛克

一、遍历图像并对每个马赛克区域进行像素化处理 for (int y 0; y < image.rows; y blockSize) {for (int x 0; x < image.cols; x blockSize) {cv::Rect rect cv::Rect(x, y, std::min(blockSize, image.cols - x), std::min(blockSize, image.rows - y));cv::Scal…...

电机控制系列模块解析(22)—— 零矢量刹车

一、零矢量刹车 基本概念 逆变器通常采用三相桥式结构&#xff0c;包含六个功率开关元件&#xff08;如IGBT或MOSFET&#xff09;&#xff0c;分为上桥臂和下桥臂。每个桥臂由两个反并联的开关元件组成&#xff0c;上桥臂和下桥臂对应于电机三相绕组的正负端。正常工作时&…...

自定义一个SpringBoot场景启动器

前言 一个刚刚看完SpringBoot自动装配原理的萌新依据自己的理解写下的文章&#xff0c;如有大神发现错误&#xff0c;敬请斧正&#xff0c;不胜感激。 分析SpringBoot自动配置原理 SpringBoot的启动从被SpringBootApplication修饰的启动类开始,SpringBootApplicaiotn注解中最…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...