多用户及时通信系统

news2025/1/10 0:43:49

目录

  • 1. QQ用户登录
    • 1.1 用户登录1
    • 1.2 用户登录2
    • 1.3 用户登录3
  • 2. 拉取在线用户
    • 3. 无异常退出
    • 4. 私聊系统
    • 5. 群聊
  • 3. 发送文件
    • 3.1 服务端推送新闻
    • 3.2 离线留言和离线发文件

1. QQ用户登录

在这里插入图片描述

1.1 用户登录1

  • qqcommon包下
    User类序列化
    在这里插入图片描述
    Message消息类序列化
    在这里插入图片描述
    MessType接口
    在这里插入图片描述
  • qqclient.utils包下
    Utility.java工具类
  • qqclient.view包下
public class QQView {
    private User u = new User();
    private String key = "";//接受用户键盘输入
    private boolean loop = true;//控制循环

    public static void main(String[] args) {
        new QQView().mainMenu();
        System.out.println("客户端退出");
    }

    public void mainMenu() {
        while (loop) {
            System.out.println("==============欢迎登陆网络通信系统==============");
            System.out.println("\t\t1 登录系统");
            System.out.println("\t\t9 退出系统");
            System.out.print("请输入你的选择: ");
            key = Utility.readString(1);
            switch (key) {
                case "1":
                    System.out.print("请输入你的用户名: ");
                    String userId = Utility.readString(50);
                    System.out.print("请输入你的密码: ");
                    String password = Utility.readString(50);
                    //设计一个类,验证用户名密码
                    if (false) {
                        System.out.println("==============欢迎(用户 " + userId + " 登录成功)==============");
                        //进入二级菜单
                        while (loop) {
                            System.out.println("\n==============网络通信系统二级菜单(用户 " + userId + " )==============");
                            System.out.println("\t\t1 显示在线用户列表");
                            System.out.println("\t\t2 群发消息");
                            System.out.println("\t\t3 私聊消息");
                            System.out.println("\t\t4 发送文件");
                            System.out.println("\t\t9 退出系统");
                            System.out.print("请输入你的选择: ");
                            key = Utility.readString(1);
                            switch (key) {
                                case "1":
                                    System.out.println("显示在线用户列表");
                                    break;
                                case "2":
                                    System.out.println("群发消息");
                                    break;
                                case "3":
                                    System.out.println("私聊消息");
                                    break;
                                case "4":
                                    System.out.println("发送文件");
                                    break;
                                case "9":
                                    System.out.println("退出系统");
                                    loop = false;
                                    break;
                            }
                        }
                    } else {
                        System.out.println("登录失败");
                    }
                    break;
                case "9":
                    System.out.println("退出系统");
                    loop = false;
                    break;
            }
        }
    }
}

1.2 用户登录2

客户端UserClientServer类
该类用于完成用户登录验证和用户注册等功能;

public class UserClientServer {

    private User u = new User();
    private Socket socket;

    public boolean checkUser(String userId, String password) {
        //创建一个user对象
        u.setUserId(userId);
        u.setPassword(password);
        boolean b = false;

        try {
            //连接到服务端
            socket = new Socket(InetAddress.getLocalHost(), 9999);
            //获取socket关联的对象输出流
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject(u);

            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            Message message = (Message) ois.readObject();
            if (message.getMessType().equals(MessageType.MESSAGE_LOGIN_SUCCEED)) {
                //启动线程,维护socket
                ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);
                clientConnectServerThread.start();
                //集合,管理线程
                ManageClientConnectServerThread.addClientConnectServerThread(userId, clientConnectServerThread);
                b = true;
            } else {
                //如果连接失败,关闭已开启的socket
                socket.close();
                System.out.println();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return b;
    }
}

客户端线程类

public class ClientConnectServerThread extends Thread {
    //socket属性
    private Socket socket;
    //构造器socket赋值
    public ClientConnectServerThread(Socket socket) {
        this.socket = socket;
    }
    //得到socket
    public Socket getSocket() {
        return socket;
    }

    @Override
    public void run() {
        while (true) {

            try {
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) ois.readObject();
                //做其它的处理

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

客户端管理线程的类
在这里插入图片描述

1.3 用户登录3

  • qqserver.server包下
    服务端,QQServer类
public class QQServer {
    private ServerSocket ss = null;
    public QQServer() {
        //端口可以写在配置文件
        try {
            System.out.println("服务端在9999端口监听");
            ss = new ServerSocket(9999);
            while (true) {
                Socket socket = ss.accept();
                //读取User对象
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                //输出Message对象
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                User u = (User) ois.readObject();
                Message message = new Message();
                if ("100".equals(u.getUserId()) && "123456".equals(u.getPassword())) {
                    message.setMessType(MessageType.MESSAGE_LOGIN_SUCCEED);
                    oos.writeObject(message);
                    //登陆成功后,创建线程和客户端保持通信
                    ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());
                    serverConnectClientThread.start();
                    //把该线程对象放入集合中管理
                    ManageClientThreads.addClientThread(u.getUserId(), serverConnectClientThread);
                } else {//登录失败
                    message.setMessType(MessageType.MESSAGE_LOGIN_FAIL);
                    oos.writeObject(message);
                    socket.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

服务端线程类
在这里插入图片描述
ManageClientThreads管理线程类
在这里插入图片描述

  • qqframe包下
    QQFrame类中启动程序

让多个用户登陆服务端,不再是"100","123456"这一个用户
在这里插入图片描述
紧接着专门写一个方法验证用户名和密码
在这里插入图片描述
单点登录
在这里插入图片描述
在这里插入图片描述

2. 拉取在线用户

补充MessageType
在这里插入图片描述
在客户端UserClientServer类中定义请求在线用户列表方法,并对服务端发出请求
在这里插入图片描述
在这里插入图片描述
在客户端的线程类中等待服务端发送数据
在这里插入图片描述
服务端代码
获取在线用户列表,即要遍历ManageClientThreads类中的hm集合,将这段遍历集合的代码封装进ManageClientThreads类中的getOnlineUser()方法
在这里插入图片描述
在服务端的线程类中接收请求用户列表的消息请求,调用getOnlineUser()方法得到在线用户列表,通过socket将数据返回给客户端
在这里插入图片描述

3. 无异常退出

在这里插入图片描述
在UserClientServer类中编写一个方法,客户端退出系统,并给服务器发送一个退出系统的message
在这里插入图片描述
在服务端响应客户端的请求,接收客户端发送的message,进行处理
在这里插入图片描述

4. 私聊系统

在这里插入图片描述

  • 客户端server包下新建MessageClientServer类
    该类用于提供和消息相关的服务方法
    在MessageClientServer类中编写一个方法并调用
    在这里插入图片描述
    在这里插入图片描述

在服务端的通信线程中接收这个message并进行转发
在这里插入图片描述
在客户端把从服务端转发过来的消息显示
在这里插入图片描述

5. 群聊

在客户端MessageClientServer类中编写一个方法,并调用;向服务端发送一个请求
在这里插入图片描述
在这里插入图片描述
在服务端的通信线程中接收这个message并进行转发(群发)
在这里插入图片描述
在客户端把从服务端转发过来的消息显示
在这里插入图片描述

3. 发送文件

在这里插入图片描述
补充MessageType
在这里插入图片描述
Message类扩充
在这里插入图片描述

  • server包下新建FileClientServer类
    该类/对象 完成文件传输服务
public class FileClientServer {
    /**
     * @param src 源文件
     * @param dest 把该文件传输到对方的哪个目录
     * @param sender 发送用户id
     * @param getter 接受用户id
     */
    public void sendFileToOne(String src, String dest, String sender, String getter) {
        //读取src文件 封装到message对象
        Message message = new Message();
        message.setMessType(MessageType.MESSAGE_FILE_MES);
        message.setSender(sender);
        message.setGetter(getter);
        message.setSrcPath(src);
        message.setDestPath(dest);
        //需要将文件读取
        BufferedInputStream bis = null;
        byte[] fileBytes = new byte[(int) new File(src).length()];//获取文件的大小(Long 字节)

        try {
            bis = new BufferedInputStream(new FileInputStream(src));
            bis.read(fileBytes);
            //将文件对应的字节数组设置到message对象
            message.setFileBytes(fileBytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //提示信息
        System.out.println("\n" + sender + "给 " + getter + " 发送文件:" +
                src + " 到对方的电脑目录" + dest);

        try {
            //发送
            ClientConnectServerThread clientConnectServerThread
                    = ManageClientConnectServerThread.getClientConnectServerThread(sender);
            Socket socket = clientConnectServerThread.getSocket();
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端接收这个消息并转发
在这里插入图片描述
客户端接收到转发消息,输出到控制台
在这里插入图片描述
客户端调用
在这里插入图片描述

3.1 服务端推送新闻

  • qqserver包下新建SendNewsToAllServer类
public class SendNewsToAllServer implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.print("请输入服务器要推送的新闻[exit退出推送新闻的线程]: ");
            String news = Utility.readString(1000);
            //构建一个消息
            Message message = new Message();
            message.setSender("服务器");
            message.setContent(news);
            message.setMessType(MessageType.MESSAGE_TO_ALL_MES);
            message.setSendTime(new Date().toString());
            System.out.println("服务器推送消息给所有人 说: " + news);

            //遍历当前所有的通信线程,得到Socket,并发送message
            Map<String, ServerConnectClientThread> hm = ManageClientThreads.getHm();

            Collection<ServerConnectClientThread> serverConnectClientThreads
                    = hm.values();
            Iterator<ServerConnectClientThread> iterator =
                    serverConnectClientThreads.iterator();
            while (iterator.hasNext()) {
                ServerConnectClientThread serverConnectClientThread = iterator.next();
                Socket socket = serverConnectClientThread.getSocket();
                try {
                    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                    oos.writeObject(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在QQServer类启动线程
在这里插入图片描述

3.2 离线留言和离线发文件

群聊消息
当用户向所有的用户发送群聊消息的时候,给离线状态的用户设置留言
在这里插入图片描述
私聊消息
当用户向某一离线用户发送私聊消息的时候,给这个离线用户设置留言
在这里插入图片描述
离线文件
当用户向某一离线用户发送文件的时候,将文件暂存在服务端中,当用户上线时,得到message
在这里插入图片描述
当离线用户登录的时候,登录成功后,统一将离线消息(群聊和私聊)和离线文件显示出来
在这里插入图片描述

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

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

相关文章

拉伯杠杆平台|沪指上涨,大金融板块领涨,有股票连续5涨停!

A股周二上午全体小幅上涨&#xff0c;大金融集体上涨&#xff0c;推动指数上行&#xff0c;商场全体动摇不大。A50期货高开高走&#xff0c;盘中暴拉超2.6%。 不过&#xff0c;部分个股仍然动摇不小&#xff0c;有多只股票接连涨停。 别的&#xff0c;新股持续分解&#xff0c…

ATAC-seq分析:数据介绍(2)

1. 简介 ATACseq (Assay for Transposase-Accessible Chromatin using sequencing) 使用转座酶在测序前有效地片段化可访问的 DNA&#xff08;DNA可极性&#xff09;。结果提供了一种绘制可访问/开放染色质基因组范围的方法。 与其他技术相比&#xff0c;ATACseq 有几个优点&am…

嵌入式开发学习之--串口通讯(下)

提示&#xff1a;本篇来做一个关于串口的输入输出实验。 文章目录前言一、项目概况1.1、项目需求1.2、项目来源1.3、开发环境1.4、项目意义1.5、项目效果展示二、开发步骤2.1、涉及硬件电路2.2、项目代码2.2.1、串口配置总结前言 前一篇文章我们介绍了串口的几种类型以及串口标…

Linux Shell 编程,运算符,条件与分支,循环

Linux Shell 编程&#xff0c;运算符&#xff0c;条件与分支&#xff0c;循环1.Shell运算符2.判断语句3.for循环4.while循环1.Shell运算符 学习如何在shell中进行各种运算操作 案例&#xff1a;计算&#xff08;57&#xff09;3的值&#xff1a; #!/bin/bash res$(((57)*3)) …

游戏物体GameObject

在unity中所有游戏物体都是GameObject&#xff0c;这也是编程中的对象。 创建物体 在hierarchy窗口中&#xff0c;右击可以创建一个物体&#xff0c;当然也可以创建空物体。 物体属性 创建完物体后&#xff0c;一般可以在此处用这些工具来改变物体。 移动&#xff0c;旋转和…

戴尔科技集团助力中国石油大学打造现代数据中心

小的时候      总是幻想着      能够躺在床上上课      没想到现在竟然实现了      没错,对于当代大学生尤其是19级、20级来说,大学生活似乎是个虚无缥缈的词汇,因为相比与在校生活,在家上网课的时间可能会更长,一不留神就上了三年的“家里蹲”。      即使…

安装配置高度安全的匿名操作系统,利用暗网情报数据抓取工具获取普通人根本查看不到的信息

安装配置高度安全的匿名操作系统,利用暗网情报数据抓取工具获取普通人根本查看不到的信息。 Whonix匿名操作系统,Whonix 是一个专注于匿名,隐私和安全的操作系统。它基于Tor匿名网络,Debian GNU / Linux和隔离安全性。DNS泄漏是不可能的,即使具有root权限的恶意软件也无法…

“多点”开花,独立走向新零售

12月7日&#xff0c;亚洲最大的数字零售服务商多点Dmall正式向港交所递交招股说明书&#xff0c;在零售行业逐渐向线上线下一体化、店仓一体模式迈进之时&#xff0c;多点Dmall成为很多传统零售商转型路上的首选合作伙伴&#xff0c;给予了资本市场一定想象空间。 但也有观点认…

【Lua】ToLua逻辑热更新

1 前言 Lua基础语法 中系统介绍了 Lua 的语法体系&#xff0c;本文将进一步介绍 Unity3D 中基于 ToLua 实现逻辑热更新。 逻辑热更新是指&#xff1a;在保持程序正常运行的情况下&#xff0c;在后台修改代码逻辑&#xff0c;修改完成并推送到运行主机上&#xff0c;主机无缝接入…

HarmonyOS原子化服务最新概念、呈现形式与触发方式

一、HarmonyOS原子化服务最新概念 总体介绍&#xff1a; 原子化服务&#xff08;Ability&#xff09;是由HarmonyOS服务开放平台接入的一种技能&#xff0c;为华为智慧服务、智慧搜索、服务直达、智慧语音以及智慧视觉等流量入口提供服务技能。原子化服务以轻量化的呈现形式&…

高级网络应用复习——TCP与UDP,ACL列表, 防火墙,NAT复习与实验(带命令)

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.知识点总结 1.传输层的协议 &#xff08;1&#xff09;TCP 和…

「实操」结合图数据库、图算法、机器学习、GNN 实现一个推荐系统

本文是一个基于 NebulaGraph 上图算法、图数据库、机器学习、GNN 的推荐系统方法综述&#xff0c;大部分介绍的方法提供了 Playground 供大家学习。 基本概念 推荐系统诞生的初衷是解决互联网时代才面临的信息量过载问题&#xff0c;从最初的 Amazon 图书推荐、商品推荐&…

TCP的三次握手四次挥手详解

想要了解TCP的三次握手和四次挥手&#xff0c;首先要了解TCP的头部结构 TCP的头部结构如下 16位源端口号&#xff1a; 客户端地址信息16位目标端口号&#xff1a; 服务端地址信息32位序列号&#xff1a; 请求报文端数据流子节开始的位置&#xff08;比如位1024&#xff5e;2…

【20天快速掌握Python】day15-网络编程

1.网络通信的概念 简单来说&#xff0c;网络是用物理链路将各个孤立的工作站或主机相连在一起&#xff0c;组成数据链路&#xff0c;从而达到资源共享和通信的目的。 使用网络的目的&#xff0c;就是为了联通多方然后进行通信&#xff0c;即把数据从一方传递给另外一方。 前…

以分页场景谈MVC设计模式

一 、需求场景 需要实现一个分页组件&#xff0c; 可以方便的进行分页操作。 二、分析需求 从分页需求出发&#xff0c;分析潜在的元素&#xff0c; 虽然只包含一个大的分页功能&#xff0c;但是潜在的元素 包含&#xff1a;上一页 下一页 首页 尾页 当前页 等等。 为什么包含…

【Oauth2】SpringBoot整合Oauth2实现认证授权

SpringBoot整合Oauth2实现认证授权 应用场景 OAuth2.0 协议的使用场景主要为&#xff1a;第三方登录和开放接口的调用 第三方登录就是使用微信等第三方的方式来登录一个应用或者网站&#xff0c;比如用微信账号登录gitee。 而开发接口的调用&#xff0c;则比如说微信、美团…

TP5的消息队列

1.首先查看项目中是否已经有think-queue目录&#xff1a;/vendor/topthink/ 微信截图_20200909142126.png 如果没有&#xff0c;则用composer安装&#xff08;安装composer参考&#xff1a;http://www.runoob.com/w3cnote/composer-install-and-usage.html &#xff09;&#x…

Qt文档阅读笔记-Qt, QML, Widgets…What Is The Difference?

Qt, QML, Widgets…What Is The Difference? 本节主要介绍了开发Qt程序最关机的几个组建。 Qt是使用C和一些C的框架设计编写出来的。 Qt Qt是一个开源的框架。 Qt作为一个框架&#xff0c;包含了许多组件&#xff0c;这些组建又在指定的模块中&#xff0c;Qt基础组件在&…

干货| 小游戏赛道变现指南

随着羊了个羊等小游戏的爆火&#xff0c;不少人发现了小游戏赛道的巨大潜力&#xff0c;也想要在此赛道有所尝试。但是很多游戏赛道的新人对于小游戏变现问题存有疑问&#xff0c;今天就来跟大家分享一下小程序游戏赛道的变现途径&#xff01; 近期FinClip 官方正在举行小游戏…

全志 芯片 Linux MIPI CSI摄像头接口开发指南 VIN DVP CSI MIPI V4l2

1 前言 1.1 文档简介 介绍 VIN&#xff08;video input&#xff09;驱动配置&#xff0c;API 接口和上层使用方法。 1.2 目标读者 camera 驱动开发、维护人员和应用开发人员。 1.3 适用范围 ​ 表 1-1: 适用产品列表 内核版本驱动文件Linux-4.9drivers/media/platform/s…