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

韩顺平老师 山寨QQ Java版 能够实现一对一聊天,一对多聊天以及在线好友显示等功能 立即下载

项目开发流程

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

需求分析

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

整体分析

  • 多用户:多个客户端
  • 服务端和客户端之间传送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 一遍

防止多用户登录同一帐号 如果用户没有登陆,则登陆,并将登陆信息放到application, 信息为用户id,用户sessionid,用户登陆时间,登陆IP 如果用户已登陆,则每次请求要检查application, 一旦用户id相同而sessionid不同,即表明该用户在其它地方登陆, 当前登陆无条件注销 注销过程为:将当前session失效,转到登陆页面, 提示用户该用户id已在哪台机器什么时间登陆了,当前登陆已注销 web.xml添加filter: SingleFilter org.com.filter.SingleFilter SingleFilter /* 立即下载

相关推荐

Java 多用户登录限制的实现方法

最近没有事情做,闲的发呆,于是写个东东练练手。这篇文章主要介绍了Java 多用户登录限制的实现方法的相关资料,需要的朋友可以参考下

Java-多用户即时通信系统-用户登录(客户端)

【代码】Java-多用户即时通信系统-用户登录(客户端)

好好学习,天天向上。 271

保姆级教程:用Python+OpenCV搞定Orbbec Gemini深度与彩色流对齐(附完整代码)

本文提供了一份详细的Orbbec Gemini深度与彩色流对齐教程,涵盖从环境配置到完整代码实现的每一步。通过解析深度流对齐原理,对比不同对齐模式,并提供工业级应用中的问题排查方法,帮助开发者快速掌握Orbbec Gemini相机的使用技巧。文章还包含进阶应用如点云生成与三维重建的实战代码。

weixin_29090917的博客 470

B站韩顺平java学习笔记(二十一)-- 多用户即时通讯系统 章节

一 项目设计的技术 1 项目框架设计 2 Java面向对象编程 3 网络编程 4 多线程 5 IO流 6 Mysql 二 项目开发流程简介 需求分析→设计阶段→实现阶段→测试阶段→实施阶段→维护阶段。 三 需求分析 1 用户登录 2 拉取在线用户列表 3 无异常退出(客户端、服务端) 4 私聊 5 群聊 6 发文件 7 服务器推送新闻 四 通讯系统整体分析 ...

LW_20180806的博客 3483

七自由度机械臂逆运动学实战:从几何简化到KDL库高效求解

本文深入探讨了七自由度机械臂逆运动学求解的实战方法。针对冗余自由度带来的挑战,文章对比了两种核心方案:一是利用任务约束进行几何简化,快速求解特定任务;二是基于DH参数法配置KDL库,实现通用高效的数值迭代求解。文中结合宇树H1机器人实例,详细阐述了从模型解析、参数提取到代码实现与验证的全流程,并提供了几何法与KDL库的适用场景对比与避坑指南。

weixin_29044713的博客 635

《遥感大模型生产级实战:从数据到决策的端到端AI工程》系列第三部分:城市洪涝灾害应急响应与评估平台实战-文章 14:项目二启动与多源异构数据对齐

我们将系统性地梳理城市洪涝场景下的所有关键数据源,从天上的卫星(光学与SAR)、空中的无人机,到地面的物联网传感器和社交媒体信息流,深入剖析每种数据在洪涝响应中的独特价值、获取方式与内在局限性。本章的核心将是一个详尽的、生产级的数据对齐技术全景,我们将分步解决三大核心对齐难题:空间对齐(将所有数据投影到统一的地理坐标系)、时间对齐(处理不同采样频率的时间序列)以及最困难的语义对齐(将文本描述与物理观测相关联)。

panshengwu的博客 2003

java线程多用户_Socket初识-多线程实现多用户登录

1、ServerSocketpackage com.video.video.common;import java.io.*;import java.net.ServerSocket;import java.net.Socket;/*** 基于TCP协议的Socket通信,实现用户登录* 服务器端*/public class Server {public static void main(Strin...

weixin_42511080的博客 775

PLDM入门(七):FRU Data Format

每个字段为TLV(Type-Length-Value)格式,具体类型、长度范围和值定义需参考。通过条件过滤(记录句柄、类型、字段类型等)分块获取FRU记录数据(可选功能)。整个FRU数据表由多个FRU记录数据块组成,每个数据块对应表2的结构(即包含。决定,每个字段按顺序排列(Type→Length→Value)通过分块传输方式写入FRU记录表数据(需终端支持写入操作)。(文档未提供表5内容,需结合标准文档完整版)。、字段数量、编码类型及具体字段的TLV数据)。无请求数据(空请求)。

weixin_44032634的博客 1762

java 多种登录方式_Java多态--用户登录方式角度看

Java多态的定义我就不说了,今天用用户登录的案例来讲解多态。用户登录功能是交互系统中的必不可少的一个功能。登录方式有以下几种用户名+密码用户名+验证码手机号+密码手机号+验证码数据传输的格式是:public class LoginUser {private String username; // 用户名 private String password; // 密码 private ...

weixin_42168230的博客 1638

WPF实战:利用Live Charts实现高性能动态曲线可视化

本文详细介绍了如何在WPF中使用Live Charts实现高性能动态曲线可视化,特别适用于工业监控和金融分析等实时数据场景。通过增量渲染、内存复用和硬件加速等核心技术,Live Charts能够高效处理高频数据更新,显著提升图表流畅度。文章提供了从基础实现到工业级优化的完整解决方案,帮助开发者应对各种性能挑战。

weixin_29189373的博客 406

PCIe 6.0 – 关于 PCI Express Gen6 您需要知道的一切

幸运的是,PCIe 6.0 FEC 足够轻,对延迟的影响最小。在电气层上,PCIe 6.0 使用 PAM4 信号(“四级脉冲幅度调制”),每个时钟周期将 2 位组合为 4 个幅度级别(00、01、10、11),与 PCIe 5.0 和前几代相比,它使用 NRZ 调制,每个时钟周期 1 位和两个幅度级别 (0, 1)。虽然 PAM4 信号更容易出错,但由于调制技术的性质,与 PCIe 5.0 相比,通道损耗不受影响,因此 PCB 上 PCIe 6.0 信号的范围将与 PCIe 5.0 相同。

qq_43416206的博客 3431

学习:韩顺平java—多用户即时通讯系统(第22章)

(1)有趣(2)设计java各个方面的技术项目框架设计java面向对象编程网络编程多线程IO流Mysql / 使用集合充当内存数据库(3)巩固旧知识,学习新知识放在qqcommon包里(两类一接口)(1)User类:存放用户信息——用户Id号userId、用户密码pwd。

weixin_47095832的博客 1088

YOLOv11模型改进-模块-引入空间池化模块StripPooling 解决遮挡、小目标

本文介绍了一种新的空间池化策略,称为,用于场景解析。结构:包括两个平行路径,分别进行水平和垂直方向的条带池化,然后通过1D卷积层进行特征调整。:结合了条带池化和传统的空间池化,分别用于捕捉长距离和短距离的依赖关系。作用捕捉长距离依赖:通过长条形的池化窗口,有效捕捉分布离散的区域之间的关系。避免不相关信息干扰:窄条形的池化窗口有助于捕捉局部上下文,防止不相关区域干扰标签预测。提高场景解析性能:在多个基准数据集上,证明了这种方法能够显著提升场景解析的效果。

qq_64693987的博客 4204

JavaStudy11(22章-多用户即时通信系统qq)—B站韩顺平

JavaStudy11(22章-多用户即时通信系统)—B站hsp 04/27-05/01 1.22章-多用户即时通信系统 1.1 QQ 聊天项目演示 1.1.1 项目 QQ 演示 1.2 为什么选择这个项目 1.2.1 项目开发流程 1.2.2 需求分析 1.2.3 界面设计 1.2.4 功能实现-用户登录 1.2.5 功能实现-拉取在线用户列表 1.2.6 功能实现-无异常退出 1.2.7 功能实现-私聊 1.2.8 功能实现-群聊 1.2.9 功能说明-发文件 1

BLWY_1124的博客 2183

HTML5+CSS3+JS小实例:扇形展开折叠菜单

你肯定见过那种圆形浮动按钮(FAB),点一下弹出几个选项。大部分实现就是菜单项从底下往上"弹"出来,排成一列——能用,但没啥记忆点。后来我看到 Path 那个经典的扇形菜单,点一下,五个按钮像花瓣一样从中心散开,每个带不同的延迟和弹性曲线。当时就觉得:这才对嘛,交互就该有点"戏剧性"。今天拆一个纯手写版本,HTML + CSS + JS,不依赖任何库。六菜单项、扇形 144° 展开、弹性过渡、点击关闭、键盘可达——该有的都有。

艾恩小灰灰的博客 164

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

B站韩顺平学Java课程——个人笔记(20章~22章)

根据B站韩顺平老师30天学会Java视频学习所记录的笔记(包含作业代码,坦克大战,多用户聊天系统(可部署多个主机))。(20章~22章)

W666888DB的博客 586

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

学习:韩顺平java—网络编程(第21章)

(1)套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准(2)通信的两端都要有Socket,是两台机器间通信的端点(3)网络通信其实就是Socket间的通信(4)Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输(5)一般主动发起通信的应用程序属客户端,等待通信请求的为服务端客户端发起连接,服务器端接收请求连接,形成一个数据通道,通过socke获取输入流/输出流,就可以进行数据的读取操作(1)基于客户端—服务端的网络通信。

weixin_47095832的博客 1817

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【Java】韩顺平Java学习笔记 第21章 网络编程

时,数据实际上并不是立即写入到最终的目标输出流(如文件或网络连接),而是先写入到了缓冲区中。如果要接受来自客户端的字符串,直接用socket.getInputStream得到的inputStream读取即可,在while循环中读取,用。这是推荐的做法,尤其是在不需要继续使用该流的场景下。方法,这个方法会关闭输出流,它会导致尚未写出的缓冲数据被丢弃,且后续的写操作将抛出异常。得到和socket关联的输出流,输入流同理(没有得到内容的话,会阻塞)输出流的写入端,从而导致任何进一步的写入操作都可能失败,并抛出。

YA____的博客 628

Java网络编程 韩顺平 自学笔记

协议(tcp/ip) TCP/IP中文译名为传输控制协议,这个协议是Internet最基本的协议、Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成。 Socket 基本介绍 套接字(Socket)开发网络应用程序被广泛采用,以至于称为事实上的标准。 通信的两端都要有Socket,是两台机器间通信的端点 网络通信其实就是Socket间的通信 Socket允许程序把网络连成一个流,数据在两个Socket间通过IO传输。 一般主动发起通信的应用程序属于客户端,等待通信

心向阳光的天域的博客 1022

循序渐进学Java笔记(Chapter22_多用户通信系统(推消息、私聊和发文件))

本文梳理了韩顺平Java课程中多用户通信系统的开发流程和功能实现。项目开发分为需求分析、设计、编码、测试和实施五个阶段,核心功能包括用户登录、在线用户列表、私聊/群聊、文件传输和新闻推送。系统采用客户端-服务器架构,通过Message类实现消息传递,使用ConcurrentHashMap管理在线用户和离线消息。具体实现涉及线程管理、消息类型处理、异常退出机制等关键技术点,并支持离线留言和文件传输功能扩展。 写于2024/05/30

ZZHow Blog 1206

非零基础自学Java (老师:韩顺平) 第21章 网络编程 21.1 网络的相关概念

非零基础自学Java (老师:韩顺平) 第21章 网络编程 21.1 网络的相关概念

代码改变世界 439

韩顺平零基础30天学会Java【章17 网络】

韩顺平零基础30天学会Java【章17 网络】

麟麟菜菜子的博客 281

韩顺平java-网络编程基础总结

(1)基于客户端/服务端的网络编程。(2)底层使用TCP/IP协议。(3)基于Socket的TCP编程。1.首先把磁盘上的文件读到程序里面去。2.然后把图片放在一个字节数组,因为图片是二进制的,放在一个字节数组比较合理。3.socket获取输出流。4.传到服务端后,首先要通过一个socket获取一个输入流,先保存在一个服务器的字节数组(内存)中去。服务端再获取一个输出流,将获取到的数据输出到一个指定的目录。(刷新打磁盘上。

weixin_51646336的博客 623

B站韩顺平java学习笔记(二十)-- 网络编程 章节

一 网络的编程概念 1 网络通信 (1)概念 两台设备之间通过网络实现数据传输; (2)网络通信 将数据通过网络从一台设备传输到另一台设备; Java.net包下提供了一系列的类或接口,供程序员使用,完成网络通信。 2 网络 (1)概念 两台或多台设备通过一定物理设备连接起来构成了网络。 (2)基于网络的覆盖范围进行分类 局域网:覆盖范围最小,仅仅覆盖一个教师或一个机房; 城域网:覆盖范围较大,...

LW_20180806的博客 3150

韩顺平0基础学Java——第33天

p653-674

m0_50959806的博客 867
上一篇: 【Java】韩顺平Java学习笔记 第21章 网络编程
下一篇: 【Java】韩顺平Java学习笔记 第23章 反射
COTAS
博客等级 码龄7年 369粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值