网络多线程开发小项目--QQ登陆聊天功能(服务端推送新闻、离线留言和文件)
9.1.5、QQ登陆聊天功能(服务端推送新闻、离线留言和文件)
9.1.5.1、服务端推送新闻
1、需求分析
2、思路分析
3、代码实现
QQServer:
1)cn.com.agree.qqserver.service.SendNewsToAllClient
package cn.com.agree.qqserver.service;import cn.com.agree.qqcommon.Message;
import cn.com.agree.qqcommon.MessageType;
import cn.com.agree.stream.MyObjectOutputStream;
import cn.com.agree.util.Utility;
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;/*** @version 1.0* @ClassName SendNewsToAll* @Description TODO 类描述* @date 2024/1/12 11:37 上午**/
@Slf4j
public class SendNewsToAllClient implements Runnable {@Overridepublic void run() {while (true) {//构建消息对象Message message = new Message();message.setSender("服务器");message.setMsgType(MessageType.MESSAGE_ONLINEAll_MS);Scanner scanner = new Scanner(System.in);log.debug("请输入要推送的服务器消息(输入exit退出):");String news = scanner.next();if("exit".equals(news)){log.debug("服务器推送线程已退出");break;}message.setContent(news);message.setSendTime(new Date().toString());log.debug(message.getSender()+" 对大家说: "+message.getContent());//遍历服务端所有的用户id得到对应的线程socket转发给对应的客户端Map<String, ServerConnectClient> hm = ManageServerConnectClient.getHm();Iterator<String> iterator = hm.keySet().iterator();while (iterator.hasNext()) {String userId = iterator.next().toString();try {ObjectOutputStream oos = new MyObjectOutputStream(ManageServerConnectClient.getServerConnectClient(userId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}}}
}
2)cn.com.agree.qqserver.service.qqServer
while (true) {socket = serverSocket.accept();//获取来自客户端发送过来到用户对象log.debug("socket Client连接成功");new Thread(new SendNewsToAllClient()).start();ObjectInputStream bis = new MyObjectInputStream(socket.getInputStream());User user = (User) bis.readObject();//获取输出流对象写入返回给客户端的消息ObjectOutputStream oos = new MyObjectOutputStream(socket.getOutputStream());og.debug("user:{}",user);Message message = new Message();...
}
4、运行效果
9.1.5.2、离线留言和文件
1、需求分析
2、思路分析
3.1、代码实现(发送离线消息)
1)cn.com.agree.qqserver.service.ManageServerConnectClient
private static Map<String, List<Message>> notOnlineMessages = new ConcurrentHashMap<>();public static void addNotOnlineMessage(String getterId, List<Message> messages){notOnlineMessages.put(getterId, messages);}public static List<Message> getNotOnlineMessage(String getterId) {return notOnlineMessages.get(getterId);}
2)cn.com.agree.qqserver.service.ServerConnectClient
case MessageType.MESSAGE_COMM_MS:log.debug("message:{}", message);log.debug(message.getSender() + " 对 " + message.getGetter() + " 说: " + message.getContent());ServerConnectClient connectClient = ManageServerConnectClient.getServerConnectClient(message.getGetter());if(connectClient==null){//做离线消息处理,将数据保存到数据库(这里保存到Map中)if(ManageServerConnectClient.getNotOnlineMessage(message.getGetter())==null){List<Message> messages = new ArrayList<>();messages.add(message); ManageServerConnectClient.addNotOnlineMessage(message.getGetter(),messages);}else{ ManageServerConnectClient.getNotOnlineMessage(message.getGetter()).add(message);}}else {//转发消息ObjectOutputStream oos2 = new MyObjectOutputStream(connectClient.getSocket().getOutputStream());oos2.writeObject(message);//如果用户不在线,可以保存到数据库做离线转发}break;
3) cn.com.agree.qqserver.service.qqServer
//去服务端查询是否有来自他的消息,有的话转发给对应的用户List<Message> notOnlineMessage = ManageServerConnectClient.getNotOnlineMessage(user.getUserId());if(notOnlineMessage!=null&¬OnlineMessage.size()>0){for (Message message1 : notOnlineMessage) {ObjectOutputStream oos2 = new MyObjectOutputStream(socket.getOutputStream());oos2.writeObject(message1);}}
4.1、效果演示
上线后收到消息
3.2、代码实现(发送离线文件)
case MessageType.MESSAGE_FILE_MESSAGE://log.debug("message:{}", message);log.debug(message.getSender()+" 给 "+message.getGetter()+" 发送了 "+message.getSrc()+" 到我的电脑的 "+message.getDesc()+" 路径");ServerConnectClient serverConnectClient = ManageServerConnectClient.getServerConnectClient(message.getGetter());if(serverConnectClient==null){//做离线消息处理,将数据保存到数据库(这里保存到Map中)if(ManageServerConnectClient.getNotOnlineMessage(message.getGetter())==null){List<Message> messages = new ArrayList<>();messages.add(message);ManageServerConnectClient.addNotOnlineMessage(message.getGetter(),messages);}else{ManageServerConnectClient.getNotOnlineMessage(message.getGetter()).add(message);}}else {//进行转发给客户端ObjectOutputStream oos4= new MyObjectOutputStream(serverConnectClient.socket.getOutputStream());oos4.writeObject(message);}break;
4.2、效果展示
300上线后成功接收
相关文章:

网络多线程开发小项目--QQ登陆聊天功能(服务端推送新闻、离线留言和文件)
9.1.5、QQ登陆聊天功能(服务端推送新闻、离线留言和文件) 9.1.5.1、服务端推送新闻 1、需求分析 2、思路分析 3、代码实现 QQServer: 1)cn.com.agree.qqserver.service.SendNewsToAllClient package cn.com.agree.qqserver.s…...
Jtti:有哪些方法可以提升Tomcat的性能?
提升 Tomcat 性能是确保 Web 应用程序快速响应并能够处理高并发请求的关键任务。以下是一些提升 Tomcat 性能的常见方法: 1. 调整JVM参数: a. 内存分配: 增加 JVM 的堆内存(Heap Memory)以提高应用程序的内存容量。使用 -Xmx 和 -Xms 参数设置…...
LeetCode 2085. 统计出现过一次的公共字符串
目录 一、题目 1、题目描述 2、接口描述 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 C代码 Python3代码 一、题目 1、题目描述 给你两个字符串数组 words1 和 words2 ,请你返回在两个字符串数组中 都恰好出现一次 的字符串的数目。 2…...

130基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原
基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原 ,输出复原前后图像,PSF频谱结果。程序已调通,可直接运行。 130 matlab盲迭代反卷积IBD (xiaohongshu.com)...
Flying HTML生成PDF添加水印
HTML转PDF并添加水印 <!-- 用于生成PDF --> <dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.1.20</version> </dependency>import java.io.File; import jav…...

MySQL 8.0 InnoDB Tablespaces之Temporary Tablespaces(临时表空间)
文章目录 MySQL 8.0 InnoDB Tablespaces之Temporary Tablespaces(临时表空间)会话临时表空间会话临时表空间的磁盘分配和回收会话临时表空间的创建创建临时表和查看临时表信息会话临时表空间相关的设置参数innodb_temp_tablespaces_dir 全局临时表空间查…...

轴承滚珠故障的理论推导与计算(修订中...)
1.缘起 轴承故障故障位置在高频,如果不即时处理,恶化后,滚珠会有单颗故障迅速恶化到多颗,如果此时电机承载较大负载,轴承的恶化,会牵连到相关的动力轴。是一个不可不进行监测的项目。 2.频谱特征 轴承的…...

NVMe系统内存结构 - PRP与PRP List
NVMe系统内存结构 - PRP与PRP List 1 为什么需要PRP2 PRP3 PRP List4 PRP寻址算法4.1 仅PRP1指向数据4.2 PRP1指向数据,PRP2指向数据4.3 PRP1指向数据,PRP2指向PRP List 本文属于《 NVMe协议基础系列教程》之一,欢迎查看其它文章。 1 为什么…...

系列二、Spring Security中的核心类
一、Spring Security中的核心类 1.1、自动配置类 UserDetailsServiceAutoConfiguration 1.2、密码加密器 1.2.1、概述 Spring Security 提供了多种密码加密方案,官方推荐使用 BCryptPasswordEncoder,BCryptPasswordEncoder 使用 BCrypt 强哈希函数&a…...

基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpRequest 提取请求行、解析请求行和优化 以及解析请求头并存储
### 知识点1:读取网络数据 客户端发送给服务器的通信数据通过封装的bufferSocketRead函数读取读取的数据存储在struct Buffer结构体实例中,可将该实例作为参数传递给解析函数 回顾Buffer.c中的bufferSocketRead函数 // 写内存 2.接收套接字数据 int b…...

数据结构-测试1
一、判断题 1.队列中允许插入的一端叫队头,允许删除的一端叫队尾(F) 队列中允许删除的一端叫队头(front),允许插入的一端叫队尾(rear) 2. 完全二叉树中,若一个结点没有左孩子&#…...

【设计模式】01-前言
23 Design Patterns implemented by C. 从本文开始,一系列的文章将揭开设计模式的神秘面纱。本篇博文是参考了《设计模式-可复用面向对象软件的基础》这本书,由于该书的引言 写的太好了,所以本文基本是对原书的摘抄。 0.前言 评估一个面向对…...

SpringBoot源码分析
一:简介 由Pivotal团队提供的全新框架其设计目的是用来简化新Spring应用的初始搭建以及开发过程使用了特定的方式来进行配置快速应用开发领域 二:运行原理以及特点 运行原理: SpringBoot为我们做的自动配置,确实方便快捷&#…...

约数个数和约数之和算法总结
知识概览 约数个数 基于算数基本定理,假设N分解质因数的结果为 可得对于N的任何一个约数d,有 因为N的每一个约数和~的一种选法是一一对应的,根据乘法原理可得, 一个数的约数个数为 约数之和 一个数的约数之和公式为 多项式乘积的…...

数据结构-怀化学院期末题(322)
图的深度优先搜索 题目描述: 图的深度优先搜索类似于树的先根遍历,是树的先根遍历的推广。即从某个结点开始,先访问该结点,然后深度访问该结点的第一棵子树,依次为第二顶子树。如此进行下去,直到所有的结点…...

小手也能用的高性能鼠标,自定义空间还挺高,雷柏VT9Pro mini上手
今年搭载PAW3395传感器的电竞鼠标很受欢迎,雷柏就出了不少型号,满足各种喜好的玩家选择,像是近期新出的搭载3395高定版的VT9Pro和VT9Pro mini,就在轻量化的基础上,满足了各种手型的玩家的使用需要,而且价格…...

CDN加速原理详解
一、CDN加速是什么意思 CDN是Content Delivery Network)英文首字母的缩写,中文翻译为内容分发网络,由于CDN是为加快网络访问速度而被优化的网络覆盖层,因此被形象地称为”网络加速器”,即CDN加速。CDN加速是通过将网站…...
sqlachemy orm create or delete table
sqlacehmy one to one ------detial to descript 关于uselist的使用。如果你使用orm直接创建表关系,实际上在数据库中是可以创建成多对多的关系,如果加上uselistFalse 你会发现你的orm只能查询出来一个,如果不要这个参数orm查询的就是多个,一对多的…...

科普小米手机、华为手机、红米手机、oppo手机、vivo手机、荣耀手机、一加手机、realme手机如何设置充电提示音
用空空鱼就可以设置,上面还有很多提示音素材还可以设置满电和低电提醒...

zookeeper应用场景之分布式的ID生成器
1. 分布式ID生成器的使用场景 在分布式系统中,分布式ID生成器的使用场景非常之多: 大量的数据记录,需要分布式ID。大量的系统消息,需要分布式ID。大量的请求日志,如restful的操作记录,需要唯一标识&#x…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...