网络多线程开发小项目--QQ登陆聊天功能(私聊群发)
9.1.4、QQ登陆聊天功能(私聊群发)
9.1.4.1、私聊功能
1、需求说明

2、思路分析

3、代码实现
QQClient:
1)cn.com.agree.qqclient.QQView.QQView
case "3":log.debug("请输入想给谁发消息(在线用户):");String getterId = Utility.readString(50).trim();log.debug("请输入想说的话:");content = Utility.readString(200).trim();//TODO 私聊bug invalid type code: AC已解决 messageClientService.sendMsgToOne(getterId,userId,content);
2)cn.com.agree.qqclient.message.MessageClientService
/*** 私聊* @param getterId 接收方id* @param senderId 发送方id* @param content 消息内容*/public void sendMsgToOne(String getterId,String senderId,String content){//创建Message对象Message message = new Message();message.setMsgType(MessageType.MESSAGE_COMM_MS);//对话,普通消息message.setGetter(getterId);message.setSender(senderId);message.setContent(content);message.setSendTime(new Date().toString());log.debug(senderId+" 对 "+getterId+" 说: "+content);//获取socket流发送message消息try {ObjectOutputStream oos = new MyObjectOutputStream(ManageClientConnectServers.getClientConnectServer(senderId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}
3)cn.com.agree.qqclient.service.ClientConnectServer
case MessageType.MESSAGE_COMM_MS:log.debug(message.getSender()+" 对 "+message.getGetter()+" 说: "+message.getContent());break;
QQServer:
1)cn.com.agree.qqserver.service.ServerConnectClient
case MessageType.MESSAGE_COMM_MS:log.debug("message:{}", message);log.debug(message.getSender() + " 对 " + message.getGetter() + " 说: " + message.getContent());//转发消息ObjectOutputStream oos2 = new MyObjectOutputStream(ManageServerConnectClient.getServerConnectClient(message.getGetter()).getSocket().getOutputStream());oos2.writeObject(message);//如果用户不在线,可以保存到数据库做离线转发break;
4、运行效果




9.1.4.2、群发功能
1、需求说明

2、思路分析

3、代码实现
Common:
cn.com.agree.qqcommon.MessageType
String MESSAGE_ONLINEAll_MS="7";//群发消息
QQClient:
1)cn.com.agree.qqclient.QQView.QQView
case "2"://TODO 群发bug invalid type code: AC待解决log.debug("请输入要说的内容:");String content = Utility.readString(100);messageClientService.sendMsgToAll(userId,content);// System.out.println("群发消息");break;
2)cn.com.agree.qqclient.message.MessageClientService
/*** 群发* @param* @param senderId 发送方id* @param content 消息内容*/public void sendMsgToAll(String senderId,String content){//创建Message对象Message message = new Message();message.setMsgType(MessageType.MESSAGE_ONLINEAll_MS);//对话,普通消息message.setSender(senderId);message.setContent(content);message.setSendTime(new Date().toString());log.debug(senderId+" 对 "+"大家说: "+content);//获取socket流发送message消息try {ObjectOutputStream oos = new MyObjectOutputStream(ManageClientConnectServers.getClientConnectServer(senderId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}
3)cn.com.agree.qqclient.service.ClientConnectServer
case MessageType.MESSAGE_ONLINEAll_MS:log.debug(message.getSender() + " 对 " +"大家说: " + message.getContent());break;
QQServer:
cn.com.agree.qqserver.service.ServerConnectClient
case MessageType.MESSAGE_ONLINEAll_MS:log.debug("message:{}", message);log.debug(message.getSender() + " 对 " + "大家说: " + message.getContent());//遍历服务端线程集合获取非发送方的线程socket进行消息转发Map<String, ServerConnectClient> hm = ManageServerConnectClient.getHm();Iterator<String> userIds = hm.keySet().iterator();while (userIds.hasNext()) {String userId = userIds.next().toString();if (!userId.equals(message.getSender())) {//获取非发送方的用户idServerConnectClient serverConnectClient = hm.get(userId);//获取socket进行消息转发ObjectOutputStream oos3 = new MyObjectOutputStream(serverConnectClient.getSocket().getOutputStream());oos3.writeObject(message);}}break;
4、运行结果



注意:上述 invalid type code: AC异常
分析:



解决

第三种解决方案代码
cn.com.agree.stream.MyObjectInputStream
package cn.com.agree.stream;import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;/*** @author * @version 1.0* @ClassName MyObjectInputStream* @Description TODO 类描述* @date 2024/1/11 2:11 下午**/
public class MyObjectInputStream extends ObjectInputStream {public MyObjectInputStream(InputStream in) throws IOException {super(in);}@Overrideprotected void readStreamHeader() throws IOException {//重写读取头部信息方法:什么也不做}}
cn.com.agree.stream.MyObjectOutputStream
package cn.com.agree.stream;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;/*** @author * @version 1.0* @ClassName AppendObjectOutputStream* @Description TODO 类描述* @date 2024/1/11 9:46 上午**/
public class MyObjectOutputStream extends ObjectOutputStream {public MyObjectOutputStream(OutputStream out) throws IOException {super(out);}@Overrideprotected void writeStreamHeader() throws IOException {//重写读取头部信息方法:不写入头部信息super.reset();}
}相关文章:
网络多线程开发小项目--QQ登陆聊天功能(私聊群发)
9.1.4、QQ登陆聊天功能(私聊群发) 9.1.4.1、私聊功能 1、需求说明 2、思路分析 3、代码实现 QQClient: 1)cn.com.agree.qqclient.QQView.QQView case "3":log.debug("请输入想给谁发消息(在线用户):");St…...
企业版多域名SSL证书
多域名SSL证书,是一种数字证书,可以用一张SSL证书保护多个独立的域名。这种证书类型适用于拥有多个不同域名的个人或者企事业单位,可以节省给每个域名购买和管理SSL证书的时间和成本。企业版多域名SSL证书只支持企事业单位申请,今…...
理解Herbrand Equivalence
笔者最近在看GVN的一系列论文,总会看到一个概念叫Herbran Equivalence,依靠这种定义,能够判断一个GVN算法是否是complete的,也即检测一个算法是否是precise的,只有找到所有Herbrand Equivalence关系的算法才能称得上是…...
【SimPy系列博客之官方example学习与解读】—— Example 3: Car Wash
Hello,CSDN的各位小伙伴们,又见面啦!今天我们要学习的例程是:Car Wash!我们开始吧! 例程背景 这个例程相对于example 2来说会简单一些,有一个洗车厂,里面有若干台洗车机器…...
前端随机验证码安全验证sdk
前端随机验证码安全验证sdk 前言介绍一、效果展示二、使用步骤1.引入库2.参数说明3.方法与事件说明4.如何通过API获取当前用户的验证状态 前端必备工具推荐网站(免费图床、API和ChatAI等实用工具): http://luckycola.com.cn/ 前言 验证码:是一种校验区分用户是…...
语境化语言表示模型
一.语境化语言表示模型介绍 语境化语言表示模型(Contextualized Language Representation Models)是一类在自然语言处理领域中取得显著成功的模型,其主要特点是能够根据上下文动态地学习词汇和短语的表示。这些模型利用了上下文信息…...
PDO【配置】
PDOr: 6040 控制字 6060 模式 6083 加速度 6084 减速度 =====================【定位1】:// 补间7 607A 定位位置 6081 定位速度 =====================【速度3】: 60FF 目标速度 =====================【力矩4…...
CMake入门教程【高级篇】管理MSVC编译器警告
😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 1.什么是MSVC?2.常用的屏蔽警告3.MSVC所有警告4.target_compile_options用法5.如何在CMake中消除MSVC的警告?6.屏蔽警告编写技巧...
【JaveWeb教程】(8)Web前端基础:Vue组件库Element之Table表格组件和Pagination分页组件 详细示例介绍
目录 1 Table表格组件1.1 组件演示1.2 组件属性详解 2 Pagination分页2.1 组件演示2.2 组件属性详解2.3 组件事件详解 接下来我们来学习一下ElementUI的常用组件,对于组件的学习比较简单,我们只需要参考官方提供的代码,然后复制粘贴即可。本节…...
llama_index 创始人为我们展示召回提升策略(提升15%)
用句子向量替换为句子向量 句子检索,将句子转化为向量。在检索的过程中,假如句子命中,则将句子周围的内容也当做检索内容。 对比句子检索和之前的按块去做切分的检索。可以看到,内容的相关性提升了8%, 构建数据的时候…...
RAG 详解
原文:GitHub - Tongji-KGLLM/RAG-Survey 目录 RAG调查 什么是RAG?RAG的范式 幼稚的 RAG高级 RAG模块化 RAG如何进行增强?RAG 还是微调?如何评估 RAG?前景 严峻的挑战多式联运扩展RAG的生态系统RAG论文清单 增强阶段 …...
【llm 部署运行videochat--完整教程】
# 申请llama权重 https://ai.meta.com/resources/models-and-libraries/llama-downloads/ -> 勾选三个模型 -> 等待接收右键信息 # 下载llama代码库 git clone https://github.com/facebookresearch/llama.git cd llama bash download.py -> email -> url …...
Talking about likes
Tutorial Hi! Tim here with another 925English lesson! In today’s lesson, we’re learning how to talk about likes and preferences. Why It’s Important: Talking about things we like is common in various situations, from meetings to casual chats over lunch…...
DeepSeek 发布全新开源大模型,数学推理能力超越 LLaMA-2
自从 LLaMA 被提出以来,开源大型语言模型(LLM)的快速发展就引起了广泛研究关注,随后的一些研究就主要集中于训练固定大小和高质量的模型,但这往往忽略了对 LLM 缩放规律的深入探索。 开源 LLM 的缩放研究可以促使 LLM…...
代码随想录算法训练营第二十一天| 回溯 216. 组合总和 III 17. 电话号码的字母组合
216. 组合总和 III 可以参考77.组合中关于选取数组的相关操作。 递归函数的返回值以及参数:一般为void类型 递归函数终止条件:path这个数组的大小如果达到k,说明我们找到了一个子集大小为k的组合了,然后当n为0的时候࿰…...
微服务架构最佳实践
我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情 构建和管理微服务是一项艰巨的任务。这是因为微服务就像多个并行的整体应用程序,它们都必须处于同步通信和并发运行时间。因此,在设计和构建…...
国内首款支持苹果Find My芯片-伦茨科技ST17H6x
深圳市伦茨科技有限公司(以下简称“伦茨科技”)发布ST17H6x Soc平台。成为继Nordic之后全球第二家取得Apple Find My「查找」认证的芯片厂家,该平台提供可通过Apple Find My认证的Apple查找(Find My)功能集成解决方案。…...
linux 01 centos镜像下载,服务器,vmware模拟服务器
https://www.bilibili.com/video/BV1pz4y1D73n?p3&vd_source4ba64cb9b5f8c56f1545096dfddf8822 01.使用的版本 国内主要使用的版本是centos 02.centos镜像下载 这里的是centos7 一.阿里云官网地址:https://www.aliyun.com/ 二. -----【文档与社区】 —【…...
Linux安装RabbitMq明白纸(无图)
Linux安装RabbitMq步骤 安装环境Erlang和RabbitMQ版本对照安装包下载地址登录Linux服务器创建安装目录将之前下载的两个rpm文件上传到这个目录下,并解压安装Erlang安装完成后,查看Erlang版本安装socat(RabbitMq安装需要这个)解压并…...
Android - CrashHandler 全局异常捕获器
官网介绍如下:Thread.UncaughtExceptionHandler (Java Platform SE 8 ) 用于线程因未捕获异常而突然终止时调用的处理程序接口。当线程由于未捕获异常而即将终止时,Java虚拟机将使用thread . getuncaughtexceptionhandler()查询该线程的UncaughtExceptio…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
