流风回雪的后花园
首页
搜索
友情链接
往期整理
  •   历史归档
  •   文章分类
  •   文章标签
流风回雪
文章
5
分类
3
标签
5
首页
搜索
友情链接
往期整理
历史归档
文章分类
文章标签
知行合一
多用户即时通讯系统的简单实现
发布于: 2022-11-10
最后更新: 2024-11-5
次查看
思考
type
status
date
slug
summary
tags
category
icon
password

多用户即时通讯系统

想起来很多年前写的一个 Demo,用 Java 实现了一个无界面端的通讯工具,简单回忆一下。

1,用户登录

为了实现服务器和客户端之间的消息交流,我先定义了三个服务器客户端共享的类或接口,分别是Message;User;MessageType接口,因为对象的传输需要对象流,所以要求对象实现序列化接口
1.服务端读取用户输入的用户信息,封装成User对象,通过:
将对象发送给服务端
2.服务端起一个serverSocket在配置的端口循环监听,每次建立连接就会获取对象输入流,读取客户端发送过来的User信息,判断用户是否合法,如果验证通过,就会获取一个对象输出流,发送一个message对象给客户端,设置messageType为LOGIN_SUCCEEDED,创建一个线程和客户端保持通讯,该线程持有socket对象和userID两个属性,启动线程并将线程放入集合中管理。如果验证不通过,就发送一个message对象并且设置messageType为LOGIN_FAILED。
3.客户端接收服务端返回的信息,如果验证通过就创建一个和服务器保持通讯的线程并且将当前的socket传给它,这就需要创建一个线程类,我命名为ClientConnectServerThread,这个类持有socket属性,编写run方法,无限循环从服务端读取信息。为了扩展,将线程放到集合中管理。需要创建一个ManageClientConnectServerThread类,这个类有一个HashMap属性key是userId,value是线程,编写一个方法,根据userId得到线程

2.拉取在线用户列表

1.客户端:因为服务端获取到一个消息时,会对它的类型进行判断,执行不同的业务逻辑代码;所以对于拉取在线用户的功能,客户端应该new一个message对象,设置messageType为GET-ONLINE-FRIEND,通过用户ID获取对应的线程,从这个线程里getSocket,再get输出流,用对象输出流包装,并将消息发送出去。 客户端监听从服务端返回的消息,如果消息类型是RETURN-ONLINE-FRIEND,就做相应的处理。
2.服务端:服务端监听从客户端发送的消息,如果消息类型是GET-ONLINE-FRIEND,就从管理线程的map里获取Key,key就是userID,获取到之后封装为message对象将消息类型设置为RETURN-ONLINE-FRIEND,通过userId get对应的线程,通过这个线程getSocket,通过socket得到输出流,用对象流包装,将message写入。

3.无异常退出

因为客户端的主线程开辟了一个无限循环接收消息的通信线程,客户退出主线程,但是这个通信线程不会自动退出,它还会一直运行。
解决方法:在主线程调用方法,给服务端发送一个退出系统的message对象,指定sender代表退出的userId,从管理线程的集合获取到线程,再获取到socket,再获取到输出流,用对象流包装,将message发送给服务器,再调用System.exit(0)结束进程;服务器如果接收到退出系统的message后,就把这个线程持有的socket关闭,并且将该线程从管理线程的集合中删除。

4.私聊

客户端:接收用户希望给某个用户发送的聊天内容,将消息封装成message对象,设置sender和getter属性messageType,通过对应的socket发送给服务器。在它的通信线程中读取到发送的message消息,并且显示即可。
服务器端:可以读取到客户端发给某个客户的消息,从管理线程的集合中,根据message对象的getterid获取到对应线程的socket,然后将message对象转发给指定客户。

5.群聊和服务器推送消息

在私聊的基础上,接收者变成所有用户,服务端遍历管理线程的集合,取出所有的userId,排除sender,获取所有的socket,通过socket获取输出流,用对象流包装,将message转发给所有人。
服务器推送消息就是给所有的用户发送一条信息,不在线的用户会在上线后第一时间收到信息。

6.发送文件

客户端:先把文件读取到程序中,得到字节数组,将字节数组封装到message对象,设置messageType和sender和getter,通过socket以对象流发送到服务端,服务端转发message给getter;getter的客户端接收到含有文件的消息后,将文件保存到磁盘。
服务端转发message给getter;getter的客户端接收到含有文件的消息后,将文件保存到磁盘。
最后客户端:

7.离线发送文件和消息

服务器: 当有用户发送文件,消息。如果接收者不在线,就把message存到服务器的一个concurrentHashMap,这个map的key就是getterID,value是一个存放Message对象的ArrayList<message>。每当有新用户登录时,服务器会查看这个集合里面有没有对应的userID,如果有,就遍历存放message对象的ArrayList<,message>,将文件发送给该对象,同时map.remove()这个键值对。
 
  • 作者:流风回雪
  • 链接:https://zone.lfhx.me/learning/java_qq
  • 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章
手写实现简易版 Tomcat 和 Servlet
基于兰空图床创建随机图片 API手写实现简易版 Tomcat 和 Servlet
Loading...
目录
0%
多用户即时通讯系统1,用户登录2.拉取在线用户列表3.无异常退出4.私聊5.群聊和服务器推送消息6.发送文件7.离线发送文件和消息
流风回雪
流风回雪
若见诸相非相 即见如来
文章
5
分类
3
标签
5
最新发布
Debian /Ubuntu 安装 Docker
Debian /Ubuntu 安装 Docker
2024-11-5
CLAW 月付4刀港机
CLAW 月付4刀港机
2024-11-5
手写实现简易版 Tomcat 和 Servlet
手写实现简易版 Tomcat 和 Servlet
2024-11-5
多用户即时通讯系统的简单实现
多用户即时通讯系统的简单实现
2024-11-5
基于兰空图床创建随机图片 API
基于兰空图床创建随机图片 API
2024-11-5
公告
 
 
 
目录
0%
多用户即时通讯系统1,用户登录2.拉取在线用户列表3.无异常退出4.私聊5.群聊和服务器推送消息6.发送文件7.离线发送文件和消息
2024流风回雪.

流风回雪的后花园 | 若见诸相非相 即见如来

Powered byNotionNext .