【Java】韩顺平Java学习笔记 第22章 多用户通讯系统

news2024/9/9 1:20:34

文章目录

  • 项目开发流程
  • 需求分析
  • 整体分析
  • 用户登录
    • 注意
  • 拉取在线用户列表
  • 无异常退出
  • 私聊功能
    • 注意
  • 发送文件
  • 服务端推送新闻
  • 接收离线消息和文件

项目开发流程

  • 需求分析
  • 设计阶段
  • 实现阶段
  • 测试阶段
  • 实施阶段
  • 维护阶段

需求分析

  • 用户登录
  • 拉取在线用户列表
  • 无异常退出(客户端、服务端)
  • 私聊
  • 群聊
  • 发文件
  • 文件服务器推送新闻

整体分析

  • 多用户:多个客户端
  • 服务端和客户端之间传送Message对象来进行通信(提高效率),可以使用对象流来读取
  • socket在线程里进行管理
  • 群发消息时需要获取所有socket——服务端需要用一个集合来管理线程(socket)
  • 一个客户端和服务端可能出现多个连接通道、多个线程(如同时传文件和聊天),故客户端也要用一个集合来管理线程,可以用hashmap管理

  • 注:User的id要统一!不能一下用String 一下用int!不然会非常麻烦!同时如果用int,id就不能为中文,故不推荐!

用户登录

  • 用 hashMap 模拟数据库,则可以实现多个用户登录
  • 共有的类:User(用户信息)、Message(传递的消息)
  • 共有的接口:MessageType(表示消息类型的接口)
  • 注意共有的类需要通过对象流进行传输,传输则需要序列化
  • 登录界面(一级菜单、二级菜单)
  • 创建socket,用于向服务端发送需要验证的User和接收服务端发来的登录确认信息Message
  • 如果登录成功,需要创建一个线程,传入socket,让这个线程不停地在端口进行监听,监听服务端发送来的信息(线程有run方法可以实现不停工作)
  • 用HashMap存储线程,方便实现多个用户同时通信
  • 验证完登录,如果登录失败,则发送User和接收Message的socket已经没有用,需要进行关闭
  • ConcurrentHashMap 替换 HashMap ,可以处理并发的集合,没有线程安全问题

注意

  • 建立链接后,不能随便关闭 ObjectOutputStream 和 ObiectInputStream ,这样会关闭建立好的socket,从而报错
  • while循环外暂时不能写 serverSocket.close(),Java编译器不允许

拉取在线用户列表

  • 客户端发送Message对象向服务端要在线用户列表信息
  • 先对Message种类进行拓展,两边同时拓展
  • Message 得到当前线程的socket 对应的 ObjectOutputStream
  • 规定在线用户列表形式:100 200 紫霞仙子
  • 在run方法中读取message信息并根据类型进行不同的处理操作
  • 在服务端的管理线程的HashMap类中写一个返回在线用户列表的方法(遍历HashMap)

无异常退出

  • 客户端选择退出系统选项后,只是退出了main方法,并没有退出创建的客户端线程,故进程还没有退出
  • 客户端解决方法:在主线程调用一个方法,给服务器端发送一个退出系统的message;调用System.exit(0)正常退出
  • 服务端解决方法:接收到一个退出的Message,将线程持有的socket关闭,退出该线程的run方法,相当于结束了该线程

私聊功能

  • 将聊天内容包装成Message对象,发送给服务端
  • 服务端读取,获取到对应线程的socket,然后将这个Message发给对应的用户
  • 在客户端线程里写一个接收方法,读取发送过来的信息

注意

  • oos = new ObjectOutputStream(ServerThreadHashMap.
                                    get(message.getSender()).getSocket().getOutputStream());
                            message1.setContent("向用户 " + message.getGetter()
                                    + " 发送数据成功!");
                            oos.writeObject(message1);//这里当时没有写这行,重新刷新oos,结果导致invalid type code: AC报错
    

    在Java中,当你尝试使用ObjectOutputStream对同一个OutputStream多次进行序列化操作,尤其是在没有正确关闭前一个ObjectOutputStream的情况下,再次创建一个新的ObjectOutputStream实例并尝试写入对象,很可能会导致java.io.StreamCorruptedException: invalid type code: AC异常。

    这是因为每当创建一个ObjectOutputStream实例时,它会在底层输出流的开始处写入一个特殊的序列化头(称为Stream Header),这个头包含了一些用于验证序列化数据格式的魔数(magic number)。对于Java,默认的魔数值是0xAC ED,用于标记这是一个Java序列化的数据流。

    当你在一个已经写入过ObjectOutputStream数据的OutputStream上再次创建一个新的ObjectOutputStream实例,没有先关闭之前的流,那么新写入的序列化头(即0xAC ED)就会紧接着前一次写入的数据之后,而不会被当作新的序列化流的开始。当在另一端使用ObjectInputStream尝试读取这些数据时,它在解析完第一个对象后遇到额外的魔数值0xAC(即type code AC),就会认为这是不合法的类型代码,因为它期望的是对象的实际数据,于是抛出了StreamCorruptedException: invalid type code: AC异常。

    为了避免这个问题,确保每次完成序列化操作后正确地关闭ObjectOutputStream,或者如果需要在同一OutputStream上进行多次序列化,考虑仅创建一个ObjectOutputStream实例并重复使用它,而不是反复创建新的实例。此外,在某些场景下,如果必须创建多个ObjectOutputStream实例,确保在创建新实例之前彻底刷新和关闭前一个实例,并考虑到这可能需要更复杂的逻辑来管理输出流的状态。

发送文件

  • 将文件读取到客户端的字节数组
  • 将字节数组封装到message对象
  • 将message对象发给服务端
  • 服务端进行转发

服务端推送新闻

  • 本质其实就是群发消息
  • 在服务器启动一条独立县城,专门负责发送推送新闻

接收离线消息和文件

  • 创建一个HashMap存放所有的离线消息和文件
  • HashMap 的 key 是接收消息的用户名,value 是 message,即消息内容
  • 每当一个用户上线后,检查这个用户名对应的 HashMap,如果有离线消息,给其传递所有的离线消息
  • 注意以下错误:

注意每次 new 的时候都会调用writeStreamHeader()方法写入4个字节的StreamHeader(看源码),标记这个是对象处理流,可能导致的错误:如果在接收方每次都是new一个新的ObjectInputStream 来接收,而发送方只 new 过一个 ObjectOutputStream,之后每次都是用new过的 ObjectOutputStream对象来发送东西,这样就会导致之后并没有添加头部。而接受方每次都是新的 new,则每次接收都要检测头部,当发送方没有提供头部时,接收方就把内容当做了头部,导致出错。解决方法之一是每次使用 ObjectOutputStream 时都重新 new 一遍

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【BES2500x系列 -- RTX5操作系统】系统执行流程 -- 引导程序(boot loader)--(十)

💌 所属专栏:【BES2500x系列】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &#x1f49…

【C++】嵌套循环案例 乘法口诀表

乘法口诀表利用嵌套循环语句就可以实现 下面是一个实例 #include<iostream> using namespace std;int main() {for (int i 1; i < 10; i){for (int j 1; j < i; j){cout << j << " * " << i << " " << i *…

Agent终于能主动进化?揭秘首个让AI自我进化的训练框架!突破人类专家局限,告别手动调优!端到端符号化框架如何引领AI自我革命

随着大型语言模型(LLMs)的兴起和AI Agent框架的开源&#xff0c;基于这些强大模型的智能体在学术界和工业界受到了极大的关注&#xff0c;并在多个场景中取得了显著的成果。然而&#xff0c;尽管AI Agent在一些应用中已经落地&#xff0c;其研究和开发仍然主要依赖于“专家中心…

Apollo:目录分析, test ok

apollo: Apollo (阿波罗)是一个开放的、完整的、安全的平台,将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统,快速搭建一套属于自己的自动驾驶系统。 - Gitee.comhttps://github.com/ApolloAuto/apolloapollo 目录名称目录作用cyber消息中间件,替换ros作为消息层…

2024年【制冷与空调设备运行操作】考试题及制冷与空调设备运行操作新版试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 制冷与空调设备运行操作考试题根据新制冷与空调设备运行操作考试大纲要求&#xff0c;安全生产模拟考试一点通将制冷与空调设备运行操作模拟考试试题进行汇编&#xff0c;组成一套制冷与空调设备运行操作全真模拟考试…

python绘制图像无法显示汉字、数字

解决的问题&#xff1a;python绘制图像无法正确显示汉字、数字&#xff0c;图中汉字数字以方块形式显示。 直接先上代码&#xff1a; # 确保图表中的汉字可以显示 plt.rcParams["font.sans-serif"] ["SimHei"] plt.rcParams["axes.unicode_minus…

25.惰性队列

介绍 消费者由于各种原因而致使长时间不能消费消息造成堆积。比如有一百万条消息发送到mq中&#xff0c;消费者这时宕机了不能消费消息&#xff0c;造成了消息堆积。惰性队列就有必要了。 正常情况下&#xff0c;消息保存在内存中。消费者从内存中读取消息消费&#xff0c;速…

【设计模式】代理模式详解

1.简介 代理模式是常用的Java设计模式&#xff0c;该模式的特点是代理类与委托类共享相同的接口。代理类主要负责预处理消息、过滤消息、将消息转发给委托类&#xff0c;并在事后处理消息等。代理类与委托类之间通常存在关联关系&#xff0c;一个代理类对象与一个委托类对象关…

TPM管理咨询公司在项目实施过程中提供哪些培训和支持?

在竞争激烈的市场环境中&#xff0c;企业项目的成功实施不仅是技术的较量&#xff0c;更是管理智慧的体现。而TPM管理咨询公司&#xff0c;作为提升企业运营效率与竞争力的专业伙伴&#xff0c;深知在项目推进的每一步中&#xff0c;专业的培训与强大的支持体系对于确保项目顺利…

shell脚本编写、一键安装nginx、条件语句、 检测网段脚本、 打印九九乘法表、

1.shell脚本 1.编写及运行脚本 [root13git ~]# vim hello.sh [root13git ~]# bash hello.sh [root13git ~]# sh hello.sh [root13git ~]# source hello.sh //在当前进程执行 [root13git ~]# chmod x hello.sh [root13git ~]# ./hello.sh 2.一键安装nginx [root13g…

小红书笔记评论采集全攻略:三种高效方法教你批量导出

摘要&#xff1a; 本文将深入探讨如何利用Python高效采集小红书平台上的笔记评论&#xff0c;通过三种实战策略&#xff0c;手把手教你实现批量数据导出。无论是市场分析、竞品监测还是用户反馈收集&#xff0c;这些技巧都将为你解锁新效率。 一、引言&#xff1a;小红书数据…

芋道源码/yudao-cloud二次开发日记(商品sku数据归类为规格属性)

商品的每一条规格和属性在数据库里都是单一的一条数据&#xff0c;从数据库里查出来后&#xff0c;该怎么归类为对应的规格和属性值&#xff1f;如下图&#xff1a; 在商城模块&#xff0c;商品的单规格、多规格、单属性、多属性功能可以说是非常完整&#xff0c;如下图&#x…

Github2024-07-29 开源项目周报Top15

根据Github Trendings的统计,本周(2024-07-29统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目2Java项目2HTML项目2C项目2TypeScript项目2JavaScript项目2非开发语言项目1Vue项目1Go项目1Dart项目1C++项目1Rust项目1Jupyter Note…

项目计划书编制方案(DOC)

项目开发计划包括项目描述、项目组织、成本预算、人力资源估算、设备资源计划、沟通计划、采购计划、风险计划、项目过程定义及项目的进度安排和里程碑、质量计划、数据管理计划、度量和分析计划、监控计划和培训计划等。 软件资料清单列表部分文档&#xff1a; 工作安排任务书…

Temporal(时效)模式01

Andy Carlson, Sharon Estepp, Martin Fowler 著&#xff0c;透明 译 抽象 在面向对象设计中&#xff0c;我们不断使用“对象”&#xff08;object&#xff09;这个词。对象不仅仅用来表现真实世界中存在的物件&#xff0c;它们也被用来表现那些曾经存在但已经消失了的物件&…

关于Docker Engine AuthZ 插件授权绕过漏洞 (CVE-2024-41110)

一、漏洞概述 漏洞名称&#xff1a;Docker Engine AuthZ 插件授权绕过漏洞 &#xff08;CVE-2024-41110&#xff09; 漏洞等级&#xff1a;高危 漏洞描述&#xff1a;DockerEngine是Docker的核心组件&#xff0c;是一 个开源的容器引擎&#xff0c;负责构建、运行和管理容器…

又一新AI搜索工具,OpenAI 推出新的搜索方式 SearchGPT

系列文章目录 每天推荐AI工具系列文章回顾&#xff1a; 选择 haiyi海艺图像生成、LoRA、模型的使用和训练网站 tusiart吐司艺术图像生成、LoRA 模型的使用和训练网站 解锁AI创造力的无限可能&#xff1a;探索Vivago.ai的革命性功能 文章目录 系列文章目录前言一、SearchGPT…

html+css+js前端作业和平精英6个页面页面带js

htmlcssjs前端作业和平精英6个页面页面带js 下载地址 https://download.csdn.net/download/qq_42431718/89595600 目录1 目录2 项目视频 htmlcssjs前端作业和平精英6个页面带js 页面1 页面2 页面3 页面4 页面5 页面6

锐捷RCNA | RGOS日常管理操作和Windows常用命令

RGOS操作系统最主要的三大特性是模块化、安全性、开放性。 RGOS平台登陆方式 平台概述 RGOS全称“锐捷通用操作系统”&#xff0c;即网络设备的操作系统 基于RGOS开发的软件版本目前为11.x&#xff0c;又被称为11.x平台优势 模块化设计&#xff0c;方便运维管理故障隔离&…

[ARC105E] Keep Graph Disconnected题解

题目 考虑加任意一条边时都会输的图的状态&#xff1a;图被分成两个强联通分量&#xff0c;每一个强联通分量都是一个完全图。 也就是说&#xff0c;假设一开始节点 1 1 1 和节点 n n n 不联通&#xff0c;那么还可以加 n ( n − 1 ) 2 − m − c n t 1 ( n − c n t 1 ) \…