【Qt聊天室客户端】聊天界面功能

1. 发送消息

1.1 实现逻辑分析

  • 发送消息的具体实现,通过输入框右下角的发送按钮
  • 输入框中发送的内容,通过网络传输给服务器
  • 客户端,发送消息成功后,消息展示区中要显示刚刚发送出去的消息

1.2 具体实现

消息输入区域设置信号槽处理函数,并在构造函数中进行调用

 发送文本消息实现

  •  考虑会话是否选中
  • 考虑文本输入内容是否为空

  • 测试

 

 

 

设计客户端发送消息(通过netClient),实现不同消息类型的发送

  • 根据消息的不同类型,填充消息内容,比对proto文件使用
message StringMessageInfo {string content = 1;//文字聊天内容
}
message ImageMessageInfo {optional string file_id = 1;//图片文件id,客户端发送的时候不用设置,由transmit服务器进行设置后交给storage的时候设置optional bytes image_content = 2;//图片数据,在ES中存储消息的时候只要id不要文件数据, 服务端转发的时候需要原样转发
}
message FileMessageInfo {optional string file_id = 1;//文件id,客户端发送的时候不用设置int64 file_size = 2;//文件大小string file_name = 3;//文件名称optional bytes file_contents = 4;//文件数据,在ES中存储消息的时候只要id和元信息,不要文件数据, 服务端转发的时候也不需要填充
}
message SpeechMessageInfo {optional string file_id = 1;//语音文件id,客户端发送的时候不用设置optional bytes file_contents = 2;//文件数据,在ES中存储消息的时候只要id不要文件数据, 服务端转发的时候也不需要填充
}
message MessageContent {MessageType message_type = 1; //消息类型oneof msg_content {StringMessageInfo string_message = 2;//文字消息FileMessageInfo file_message = 3;//文件消息SpeechMessageInfo speech_message = 4;//语音消息ImageMessageInfo image_message = 5;//图片消息};

DataCenter中实现addMessage()方法

 发送消息到显示界面逻辑

服务器逻辑实现

阶段性测试  

  • 细节问题修复
    • 会话消息实时展示(使用信号槽的方法实现)
    • 发送方头像边框去除

2. 接收消息

2.1 实现逻辑分析

  1. 客户端通过HTTP向服务器发送消息
  2. 服务器根据HTTP发送的消息,也就是根据两个用户对话(单聊)还是多个用户对话(群聊)判断,同时根据chatSessionId判断是哪个用户发起的对话
  3. 服务器构建好消息后,将这个消息通过websocket转发给该会话中的用户

消息加载与处理逻辑

  • 需求分析
    • 消息慢加载机制
      • 减少初始加载时候的开销,只有当用户点击某个会话的时候,才会加载会话的消息列表
      • 简单来说,用户如果没有点击某个会话,那么在本地hash数据结构中,就不会存在该会话的消息列表
    • websocket实时消息接收
      • 如果当客户端通过websocket收到某个会话的新消息时,如果该会话的消息列表没有提前加载到本地,直接在本地保存不太方便
      • 新消息直接通过服务端返回完整的消息列表获取,而不是单独存储新的消息
  • 加载会话列表逻辑
    • 检查该会话的 chatSessionId 是否已经在本地 hash 数据结构中存在
    • 如果不存在,则通过网络请求从服务器加载该会话的完整消息列表
    • 将该消息列表存储在本地的 hash 中(QHash<QString, QList<Message>>
    • 然后,展示该会话的消息列表

  • websocket收到新消息逻辑
    • WebSocket 返回的消息数据已经包含该会话的完整消息列表,因此不需要单独存储这条新消息
    • 直接将收到的完整消息列表,替换或更新本地 hash 中对应会话的消息列表
    • 更新后的消息列表就可以直接用于展示

  • 新消息到达但是用户没有查看
    • 最新一条消息设置为该会话的“消息预览”
    • 更新会话的“未读消息数”,在界面上显示未读消息提醒

信号槽更新消息列表逻辑

  • NetClient收到消息:服务器通过websocket向客户端发送消息,NetClient收到消息后开始处理消息,并将其保存到本地的消息列表中
  • 发送信号通知界面更新:NetClient解析完消息后,发送信号,通知前端界面更新显示区域
  • 界面槽函数接收信号并更新显示:在MessageShowArea的槽函数中,收到信号后将新消息追加到显示区域中;对于自己发送的消息,在MessageEditArea中,同样会将消息添加到消息展示区中

客户端与服务连接断开时的逻辑分析

客户端与服务端连接断开出现的问题

  • 客户端与服务端建立连接
    • 客户端连接服务器的时候,服务器会收到一个Socket对象,并发出一个Connect信号槽
    • 此时,服务器生成一个hash,并将信号槽与socket对象之间的关系进行记录,简单来说就是服务器在管理连接的过程中会将每个socket对象与其对应的处理逻辑(信号槽)关联起来
  • 断开连接后
    • 客户端与服务器断开连接后,服务器相应的socket对象失效,也就是这个socket对象不再代表一个有效连接
    • 尽管该socket已经失效,但是服务器中仍然保留里信号槽与之前socket对象之间的关系
  • 新客户端重新连接后出现问题
    • 此时如果新的客户端连接到了服务器,触发之前信号槽的回调逻辑,但是由于旧的socket对象依然是与信号槽绑定,服务器就会尝试使用已经失效的socket进行通信
    • 当使用已经失效的socket进行通信的时候,自然就会导致程序错误或者不可预测的行为

解决思路

  • 连接断开后,需要确保相应信号槽与旧的socket的关联及时被清除,避免野指针的出现
  • 检查socket是否有效

2.2 具体实现

Protobuf分析

  • 服务器推送给客户端消息类型
    • 添加好友申请
    • 好友申请处理
    • 好友删除(双方实现互相删除)
    • 创建群聊会话
    • 接收消息

信号槽更新消息列表逻辑实现 

 消息更新逻辑测试

显示未读消息数量(收到的消息不是指定会话)

  •  显示未读消息逻辑
    • 构建会话Item(SessionItem)的时候
    • 更新最后一条消息(updateLastMessage)时需要显示未读消息逻辑
    • 点击未读消息active的时候,需要将未读消息清空

 

 测试服务端

  • 通过点击按钮,控制websocket服务器,给客户端发送消息

补充:客户端与服务器之间的连接断开时的实现(逻辑分析参2.1)

  •  启动的时候释放旧的socket

服务端Bug解决(测试客户端书写完成后无法实现向客户端发送消息) 

  •  问题复现

  •  点击按钮后信号正常进行了发送

  • 添加日志,判断连接该信号的信号槽是否出现错误

  •  结果:添加日志后重新运行,添加的日志没有按照正常逻辑打印
  • 继续检查逻辑,打开测试网络逻辑,打印具体日志

 

  • 结论:该处无错误
  • 检查websocket初始化时测试连接是否成功时的逻辑判断错误,从而导致下述日志不打印而直接返回的情况

 

  • 解决文件加载失败与头像资源加载问题

  •  修改后加载资源和头像资源获取成功
  • 问题:客户端仍然是没有显示出未读消息,进一步考虑客户端处理响应出现错误

  • 分析是否updateLastMessage逻辑出现错误

  •  检查信号是否正确发送

 

  •  结论:信号没有正常发送,分析信号没有正常发送的原因
  • 进一步检查信号槽连接是否正确

  •  再次梳理NetClient

  • 修复未读消息显示错误

  • 添加检查日志,强制刷新内容 

 

  • 结论:逻辑都可以正常运行,但是界面没有正常更新 
  • 继续检查更新后的文本text内容是否错误

 

 测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/456910.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cout输出应用举例

Cout输出应用 在main.cpp里输入程序如下&#xff1a; #include <iostream> //使能cin(),cout(); #include <stdlib.h> //使能exit(); #include <sstream> #include <iomanip> //使能setbase(),setfill(),setw(),setprecision(),setiosflags()和res…

Unity2D 人物爬楼梯

unity3d 中 实现 2d角色爬梯子功能。_哔哩哔哩_bilibiliunity3d 中 实现 2d角色爬梯子功能。, 视频播放量 2598、弹幕量 3、点赞数 28、投硬币枚数 18、收藏人数 83、转发人数 19, 视频作者 Fss1975, 作者简介 &#xff0c;相关视频&#xff1a;寻路算法 在unity3d 中的演示&am…

05方差分析续

文章目录 1.Three way ANOVA2.Latin square design2.Hierarchical (nested) ANOVA3.Split-plot ANOVA4.Repeated measures ANOVA5.Mixed effect models 1.Three way ANOVA 三因素相关分析 单因子分析的代码 data(mtcars) nrow(mtcars) # 32 mtcars$cyl as.factor(mtcars$cyl…

【永中软件-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

spring整合使用xml方式整合Druid数据源连接池

1.普通的JDBC数据库连接使用 DriverManager 来获取&#xff0c;每次向数据库建立连接的时候都要将 Connection加载到内存中&#xff0c;再验证用户名和密码(得花费0.05s&#xff5e;1s的时间)。需要数据库连接的时候&#xff0c;就向数据库要求 一个&#xff0c;执行完成后再断…

【微服务】Java 对接飞书多维表格使用详解

目录 一、前言 二、前置操作 2.1 开通企业飞书账户 2.2 确保账户具备多维表操作权限 2.3 创建一张测试用的多维表 2.4 获取飞书开放平台文档 2.5 获取Java SDK 三、应用App相关操作 3.1 创建应用过程 3.2 应用发布过程 3.3 应用添加操作权限 四、多维表应用授权操作…

语音识别——使用Vosk进行语音识别

文章目录 前言一、Vosk模型1.准备好所需要的语音包2.下载使用 二、使用示例1.文件读取示例2.结合麦克风演示 总结 前言 如何编译Vosk请参照之前的文章&#xff0c;ubuntu编译kaldi和vosk Vosk是语音识别开源框架&#xff0c;支持二十种语言 - 中文&#xff0c;英语&#xff0…

使用Prometheus对微服务性能自定义指标监控

背景 随着云计算和容器化技术的不断发展&#xff0c;微服务架构逐渐成为现代软件开发的主流趋势。微服务架构将大型应用程序拆分成多个小型、独立的服务&#xff0c;每个服务都可以独立开发、部署和扩展。这种架构模式提高了系统的可伸缩性、灵活性和可靠性&#xff0c;但同时…

大数据-190 Elasticsearch - ELK 日志分析实战 - 配置启动 Filebeat Logstash

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

语音语言模型最新综述! 关于GPT-4o背后技术的尝试

近期,大型语言模型(LLMs)在生成文本和执行各种自然语言处理任务方面展现出了卓越的能力,成为了强大的AI驱动语言理解和生成的基础模型。然而&#xff0c;仅依赖于基于文本模态的模型存在显著局限性。这促使了基于语音的生成模型的发展,使其能够更自然、直观地与人类互动。 为了…

任务看板是什么?如何选择合适的任务看板工具?

一、任务看板是什么&#xff1f; 任务看板是一种可视化的项目管理工具&#xff0c;它通常以板状的形式呈现&#xff0c;将任务以卡片的形式展示在不同的列中&#xff0c;每一列代表任务的不同状态。例如&#xff0c;待办事项、进行中、已完成等。任务看板能够帮助团队成员清晰…

Linux: network: wireshark IO图的一个问题

今天遇到一个问题&#xff0c;发现wireshark画的IO图&#xff0c;前几秒没有数据&#xff0c;但是根据Raw的pcap看&#xff0c;是有包的&#xff0c;这就迷惑了。 经同事提醒&#xff0c;这个IO在设置了多个画图filter的时候&#xff0c;可能导致开始前几秒没有输出。如下图 这…

LLM | 论文精读 | 基于大型语言模型的自主代理综述

论文标题&#xff1a;A Survey on Large Language Model based Autonomous Agents 作者&#xff1a;Lei Wang, Chen Ma, Xueyang Feng, 等 期刊&#xff1a;Frontiers of Computer Science, 2024 DOI&#xff1a;10.1007/s11704-024-40231-1 一、引言 自主代理&#xff08;…

找不到包的老版本???scikit-learn,numpy,scipy等等!!

废话不多说 直接上链接了&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple/https://pypi.tuna.tsinghua.edu.cn/simple/https://pypi.tuna.tsinghua.edu.cn/simple/xxx/ 后面的这个xxx就是包的名字 大家需要什么包的版本&#xff0c;直接输进去就可以啦 举个栗子&#…

关于Docker的docker engine stopped问题解决

问题图: 主要检查这两块 启用或关闭Windows功能如下图&#xff08;将没开启的开启特别是Hyper-V&#xff0c;Linux&#xff0c;虚拟机等&#xff09;&#xff1a; 然后打开任务管理器搜索Docker service将关闭状态打开 运行管理员CMD执行如下命令 重启&#xff01;&#xff01…

ClickHouse在百度MEG数据中台的落地和优化

导读 百度MEG上一代大数据产品存在平台分散、质量不均和易用性差等问题&#xff0c;导致开发效率低下、学习成本高&#xff0c;业务需求响应迟缓。为了解决这些问题&#xff0c;百度MEG内部开发了图灵3.0生态系统&#xff0c;包括Turing Data Engine(TDE)计算引擎、Turing Dat…

个性化头像新选择:A1快速定制你的专属头像

个性化头像是彰显个人特色的绝佳方式&#xff0c;许多人为了表达自我&#xff0c;都会选择定制专属头像。然而&#xff0c;传统的定制头像服务往往价格不菲&#xff0c;且效果难以预测。幸运的是&#xff0c;AI绘画技术的发展为这一问题提供了解决方案。尽管许多AI绘画平台需要…

useEffect简单介绍

react组件生命周期 比如说&#xff0c;某些操作就只在初始渲染后执行&#xff0c;我们就可以使用useEffect。 useEffect(function () {fetch(http://www.omdbapi.com/?apikey${KEY}&sinterstellar).then((res) > res.json()).then((data) > setMovies(data.Search)…

fpga系列 HDL: 竞争和冒险 01

卡诺图是一种逻辑化简工具&#xff0c;用来在布尔函数的最小项和形式中&#xff0c;找到冗余项并实现逻辑化简。也可用于HDL中竞争和冒险的判断。 最小项 任何一个逻辑函数都能化简为最小项的和的形式对于 n 个变量的布尔表达式&#xff0c;每个变量都必须以原变量&#xff0…

Pyramidal Flow使用指南:快手、北大、北邮,开源可免费商用视频生成模型,快速上手教程

什么是 Pyramidal Flow&#xff1f; Pyramidal Flow 是由快手科技、北京大学和北京邮电大学联合推出的开源视频生成模型&#xff0c;它是完全开源的&#xff0c;发布在 MIT 许可证下&#xff0c;允许商业使用、修改和再分发。该模型能够通过文本描述生成最高10秒、分辨率为128…