当前位置: 首页 > 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注解中最…...

如何扩展MVVM架构:添加新功能与模块化设计的终极指南

如何扩展MVVM架构&#xff1a;添加新功能与模块化设计的终极指南 【免费下载链接】Android-MVVM-Architecture MVVM Kotlin Retrofit2 Hilt Coroutines Kotlin Flow mockK Espresso Junit5 项目地址: https://gitcode.com/gh_mirrors/mv/Android-MVVM-Architecture …...

Go语言的sync.RWMutex性能优化

Go语言中的sync.RWMutex是并发编程中常用的读写锁&#xff0c;它在高并发场景下对共享资源的保护至关重要。随着业务规模的扩大&#xff0c;RWMutex的性能瓶颈可能成为系统吞吐量的制约因素。本文将深入探讨如何优化RWMutex的使用&#xff0c;帮助开发者提升程序性能。 **减少…...

nuScenes数据集实战指南:从安装到多传感器数据可视化

1. nuScenes数据集简介与安装指南 第一次接触nuScenes数据集时&#xff0c;我被它丰富的传感器配置震撼到了——6个摄像头、1个激光雷达、5个毫米波雷达的同步数据&#xff0c;这简直就是自动驾驶研究的"黄金标准"。作为目前最权威的自动驾驶开源数据集之一&#xff…...

从理论到实践:忆阻神经网络中的突触与神经元电路设计探析

1. 忆阻神经网络基础&#xff1a;从生物启发到硬件实现 记得第一次接触忆阻神经网络时&#xff0c;我被它巧妙模拟生物神经系统的方式震撼到了。这种将生物神经元特性用电子元件实现的技术&#xff0c;正在重新定义人工智能硬件的可能性。忆阻器作为核心元件&#xff0c;其独特…...

Cisco 18系列AP通过u-boot实现tftp镜像启动的详细步骤解析

1. 理解Cisco 18系列AP的u-boot启动机制 当你拿到一台Cisco 18系列AP设备时&#xff0c;可能会遇到需要从网络加载镜像进行启动的情况。这就像我们电脑坏了需要从U盘重装系统一样&#xff0c;只不过这里用的是tftp协议通过网络来传输系统镜像。u-boot就是这个过程中的关键角色&…...

从零搭建微信支付商户后台:Spring Boot + Maven实战入门

1. 从Android开发到后台系统的跨界之旅 作为一个常年和Android Studio打交道的移动端开发者&#xff0c;第一次接触微信支付商户后台开发时&#xff0c;那种手足无措的感觉我至今记忆犹新。公司项目突然需要接入支付功能&#xff0c;后台开发人手不足&#xff0c;这个任务就落在…...

从YOLOv5到v8:行人跌倒检测模型演进与Web系统实战

1. YOLO系列模型演进史&#xff1a;从v5到v8的技术跃迁 第一次接触YOLOv5时&#xff0c;我被它的"开箱即用"特性惊艳到了。记得当时在一个安防项目中&#xff0c;仅用不到200行代码就实现了实时车辆检测&#xff0c;这在之前的v3时代简直不可想象。如今YOLO系列已经进…...

**发散创新:用Go语言打造高可用可观测性系统——从日志到链路追踪的实战落地**在现代微服务架构中,**可观测性(Observ

发散创新&#xff1a;用Go语言打造高可用可观测性系统——从日志到链路追踪的实战落地 在现代微服务架构中&#xff0c;可观测性&#xff08;Observability&#xff09; 已成为保障系统稳定运行的核心能力之一。它不仅仅是监控指标的堆砌&#xff0c;更是对系统行为的理解与反馈…...

Linux系统nobody用户全解析:为什么你的Apache/Nginx默认用它?

Linux系统nobody用户安全机制深度剖析&#xff1a;从Web服务到系统防护 第一次在服务器上看到nobody用户时&#xff0c;很多运维新手都会心头一紧——这个看似"无名氏"的账户会不会是黑客留下的后门&#xff1f;实际上&#xff0c;这个UID为65534的特殊用户恰恰是Lin…...

dplyr和tidyr用法释

1. 引入 在现代 AI 工程中&#xff0c;Hugging Face 的 tokenizers 库已成为分词器的事实标准。不过 Hugging Face 的 tokenizers 是用 Rust 来实现的&#xff0c;官方只提供了 python 和 node 的绑定实现。要实现与 Hugging Face tokenizers 相同的行为&#xff0c;最好的办法…...