使用Java网络编程,窗口,线程,IO,内部类等实现多人在线聊天1.0

1.整体思路

思路图

5b3c97a5649f45698a019a67b5c66527.png

整体思路如上: 涉及知识点:线程+网络编程+集合+IO等

 

TCP 协议

d1e074db85854c009a0f3ddcbb83c3cf.png

 2.代码实现过程

服务端

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server extends JFrame {//继承窗口来实现窗口功能
    /*设置接受客户端的集合,把接入服务器的客户端存入集合,方便后续的消息转发*/
    ArrayList<Socket> socketsClients = new ArrayList<>();

    /*由于下面线程需要调用窗口的一些东西,所以需要全局变量*/
    JTextArea jTextArea;
    JTextArea jTextSend = new JTextArea(30,20);//只能设置几列
    JButton jButtonSend = new JButton("发送") ;
    public Server() {
        //创建服务器窗口 一些列属性
        //主面板
        JPanel priorPanel = new JPanel(new BorderLayout());

        //显示消息
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗口结束程序
        this.setTitle("来自客户端的消息");
        this.setSize(500, 500);
        jTextArea = new JTextArea();//显示客户端的信息
        jTextArea.setEditable(false);//不可以修改 面板信息

        JScrollPane clientInformation = new JScrollPane(jTextArea);

        priorPanel.add(clientInformation,BorderLayout.CENTER);
        //写一个发布公告的窗口
        JPanel sendPanel = new JPanel();//默认流式布局
        JScrollPane jScrollPane = new JScrollPane(jTextSend);
        jScrollPane.setPreferredSize(new Dimension(400,50));

        sendPanel.add(jScrollPane);
        sendPanel.add(jButtonSend);
        priorPanel.add(sendPanel,BorderLayout.SOUTH);

        this.add(priorPanel);

        //创建监听发送键 
        jButtonSend.addActionListener(new ActionListener() {
        /*用来对每个客户端发送公告*/

            @Override
            public void actionPerformed(ActionEvent e) {
                String announcement = "来自服务器的公告:"+jTextSend.getText()+"\n";
                //把公告发布到聊天界面
                jTextArea.append(announcement);

                /*使用for循环来遍历每个客户端的对象*/
                for(Socket soc:socketsClients){
                    DataOutputStream dataOutputStream = null;
                    try {
                        dataOutputStream = new DataOutputStream(soc.getOutputStream());
                        dataOutputStream.writeUTF(announcement+"\n");
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
                jTextSend.setText(null);
            }
        });


        this.setVisible(true);
//===================================================================================
//以上为窗口的创建,下面为功能的实现
        try {
            //创建服务器对象 设置端口
            ServerSocket serverSocket = new ServerSocket(9998);
            
            //使用无限循环来不停接受客户端的连接
            while(true){
                Socket socketClient = serverSocket.accept();

                //接收到一个就向集合加入一个客户端
                socketsClients.add(socketClient);
                //就收一个连接就在后台提示一遍
                System.out.println("有"+socketsClients.size()+"个邓钦文连接到服务器!");
                
                //然后启动该客户端的线程  线程的实现则需要我们使用内部类
                new SocketThread(socketClient).start();
            }

            //处理客户端输入的东西

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器启动失败!");
        }


    }
    //创建监听

    //创建内部类 线程
    class SocketThread extends Thread{
        DataInputStream dataInputStream;
        Socket socket;
        /*构建方法 传入当前客户的连接*/
        public SocketThread(Socket socket) throws IOException {
        /*接受客户端的输入流*/
            dataInputStream = new DataInputStream(socket.getInputStream());
            this.socket = socket;
        }
        /*重写run方法 来实现对客户端的操作方法*/
        @Override
        public void run() {
            while(true){
                try {

                    String msg = dataInputStream.readUTF();
                    /*读取客户端的信息 并打印到自己的窗口上*/
                    jTextArea.append(msg+"\n");
                    //给每一个客户端发送信息  实现群聊的效果
                    for(Socket soc:socketsClients){
                        DataOutputStream dataOutputStream = new DataOutputStream(soc.getOutputStream());
                        dataOutputStream.writeUTF(msg+"\n");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("读取失败!");
                    socketsClients.remove(socket);
                    return;
                }

            }
        }


    }

}

客户端

登录界面

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;

public class EnterFrame extends JFrame {
    public EnterFrame() throws HeadlessException {

        this.setSize(600,500);
        this.setTitle("欢迎登录");
        this.setResizable(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗口结束程序
        this.setLocationRelativeTo(this);


        JPanel jPanelLast = new JPanel(new GridLayout(4,1));

        //头顶部分
        JPanel jPanelTop = new JPanel();

        JLabel jLabel = new JLabel("欢迎登录");

        jLabel.setFont(new Font("宋体",Font.BOLD,30));

        //中间部分
        JPanel jPanelMiddle = new JPanel(new GridLayout(2,1,0,0));

        JPanel jPanelAccount = new JPanel(new FlowLayout());
        
          //账号密码输入端
        JLabel jLabelAccount = new JLabel("账号");
        JTextField jTextFieldAccount = new JTextField(15);
        jPanelAccount.add(jLabelAccount);
        jPanelAccount.add(jTextFieldAccount);



        JPanel jPanelPassword = new JPanel(new FlowLayout());
        JLabel jLabelPassword = new JLabel("密码");
        JPasswordField jTextFieldPassword = new JPasswordField(15);
        jPanelPassword.add(jLabelPassword);
        jPanelPassword.add(jTextFieldPassword);
        //底部  登录按钮端
        JPanel jPanelFoot = new JPanel();

        JPanel jPanelButton = new JPanel(new FlowLayout());
        JButton enterButton = new JButton("登录");
        JButton signButton = new JButton("注册");
        jPanelButton.add(enterButton);
        jPanelButton.add(signButton);

        jPanelTop.add(jLabel);
        jPanelMiddle.add(jPanelAccount);
        jPanelMiddle.add(jPanelPassword);
        jPanelFoot.add(jPanelButton);

        jPanelLast.add(jPanelTop);
        jPanelLast.add(jPanelMiddle);
        jPanelLast.add(jPanelFoot);


        this.add(jPanelLast);
        this.setVisible(true);
//================================================================================
//以上为登录界面窗口的设计  可以自己设计

//设计监听事件  来判断用户的读取
        enterButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
//1.判断不能为空
                if(jTextFieldAccount.getText().length()<=0||jTextFieldPassword.getText().length()<=0) {
                    JOptionPane.showMessageDialog(null, "输入的账号或密码为空!");
                    return;
                }
//2.输入只能为数字与字母
                if((jTextFieldAccount.getText().matches("[a-zA-Z0-9]*")&&jTextFieldPassword.getText().matches("[a-zA-Z0-9]*"))==false){
                    JOptionPane.showMessageDialog(null,"输入的账号或密码只能为字母和数字");
                    return;
                }

//如果都满足了登录成功 创建 客户端对象 输入服务器地址 与端口  关闭登录界面

                try {
                    Socket socket = new Socket("127.0.0.1", 9998);
                    new ChatFrame(jTextFieldAccount.getText(),socket);
                    dispose();//关闭了登录窗口
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                    JOptionPane.showMessageDialog(null,"无法连接服务器");
                }


            }
        });



    }



}

聊天界面

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ChatFrame extends JFrame {
    JTextArea jTextArea;
    public ChatFrame(String account , Socket socket) throws HeadlessException {
        this.setSize(700, 600);
        this.setTitle("欢迎来到"+account+"聊天室");
        this.setResizable(true);
        this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

        JPanel jPanelEnd = new JPanel( new BorderLayout());//最终面板

        jTextArea = new JTextArea();
        jTextArea.setEditable(false);
        JScrollPane jScrollPane1 = new JScrollPane(jTextArea);
        jPanelEnd.add(jScrollPane1,BorderLayout.CENTER);

        JPanel jPanelInput = new JPanel();
        JTextArea jTextArea2 = new JTextArea(5,40);
        //带滑动的窗口
        JScrollPane jScrollPane2 = new JScrollPane(jTextArea2);//不能通过add加入,只能通过构造方法加入,这样不会出现不显示的问题


        jPanelInput.add(jScrollPane2);

        JButton jButtonSend = new JButton("发送");
        jPanelInput.add(jButtonSend);


        jPanelEnd.add(jPanelInput,BorderLayout.SOUTH);
        this.add(jPanelEnd);

        try {
            new ClientThread(socket).start();
        } catch (IOException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null,"发送错误");
        }
//关闭窗口,显示登录窗口
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("你确定要关闭我妈?");
                int res = JOptionPane.showConfirmDialog(null,"你确定要关闭我吗","操作提示",JOptionPane.OK_CANCEL_OPTION);
                if(res==0){
                    //点击确定
                    new EnterFrame();
                    dispose();//关闭当前对象
                }
            }
        });
        //监听发送事件
        try {
            DataOutputStream socketOutput = new DataOutputStream(socket.getOutputStream());
            String message = socketOutput.toString();
            jButtonSend.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    if(message.length()<=0){
                        JOptionPane.showMessageDialog(null,"输入消息不能为空!");
                        return;
                    }

                    String msg = account+" "+ new SimpleDateFormat("yyyy-MM HH:mm:ss").format(new Date()) +"\n"+jTextArea2.getText();
                    try {
                        socketOutput.writeUTF(msg);
                        System.out.println(msg);
                        jTextArea2.setText("");

                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                        JOptionPane.showMessageDialog(null,"发生错误");
                    }
                }

            });

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

        this.setVisible(true);
//=======================================================================================
//窗口的创建以及窗口功能的实现
    }

//创建内部列 创建客户端的线程,解决多个聊天窗口同时实现
    class ClientThread extends  Thread{
        DataInputStream inputStream;
        Socket socket;
        /*构造方法*/
        public ClientThread(Socket socket) throws IOException {
            inputStream = new DataInputStream(socket.getInputStream());
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                while(true){
            /*把接受的到信息添加到窗口中*/
                    String msg = inputStream.readUTF();
                    jTextArea.append(msg+"\n");
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }
    }
}

启动程序

public class RunOfServer {
    public static void main(String[] args) {
        new Server();
    }
}
public class RunOfClient {
    public static void main(String[] args) {
        new EnterFrame();
    }
}

3.实现结果

1.启动服务器

16182041264b49778e2ebac0c2d25cf0.png

2.尝试启动 3个客户端  并登录

6c3652a6f8204a21a45bfd4673edef3c.png 5d985973b0ab475eaa8ff03c7b25195d.png

 3.测试消息发送接收以及公告发送功能.

803003105bc245249faa05dd85651dfb.png

4.总结

本次聊天室1.0的简单实现使用了 Java 的网络编程 IO 线程 异常的抛出 集合 内部类 GUI等 

希望指出错误并提供改进意见 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL手工注入漏洞测试(Sql Server数据库)-墨者

———靶场专栏——— 声明&#xff1a;文章由作者weoptions学习或练习过程中的步骤及思路&#xff0c;非正式答案&#xff0c;仅供学习和参考。 靶场背景&#xff1a; 来源&#xff1a; 墨者学院 简介&#xff1a; 安全工程师"墨者"最近在练习SQL手工注入漏洞&#…

大模型应用设计的10个思考

技术不是万能的&#xff0c;但没有技术却可能是万万不能的&#xff0c;对于大模型可能也是如此。基于大模型的应用设计需要聚焦于所解决的问题&#xff0c;在自然语言处理领域&#xff0c;大模型本身在一定程度上只是将各种NLP任务统一成了sequence 到 sequence 的模型。利用大…

使用 Webshell 访问 SQL Server 主机并利用 SSRS

本文将指导您使用RDS SQL Server实例的主机账号登录和管理SQL Server Reporting Services&#xff08;SSRS&#xff09;数据库。 背景信息 RDS SQL Server提供Webshell功能&#xff0c;用户可以通过Web界面登录RDS SQL Server实例的操作系统。通过Webshell&#xff0c;用户可…

一次重新加载所有 maven 项目产生的 OOM

1、解决什么问题&#xff1f; 忘了截图了&#xff0c;用文字描述就是由于Reload All Maven Projects导致的 OOM 异常。 2、尝试与解决 2.1、尝试 2.1.1、尝试清理idea缓存&#xff08;无效&#xff09; 2.1.2、重启idea&#xff08;无效&#xff09; 2.1.3、重启电脑&am…

硬件连通性测试对象与实施过程

硬件连通性测试是一种系统性的测试方法&#xff0c;用于验证硬件设备之间的连接、通信和协作是否正常。这包括各种硬件组件&#xff0c;如计算机、网络设备、传感器、打印机等。测试的目的是确保硬件设备在其设计和运行环境中能够正确地交互和通信。 一、硬件连通性测试对象 网…

Slurm集群管理系统

Slurm集群管理系统 Slurm&#xff08;Simple Linux Utility for Resource Management&#xff0c;https://slurm.schedmd.com/&#xff09;是一个开源的、容错的、高度可扩展的集群管理和作业调度系统&#xff0c;适用于大型和小型高性能计算&#xff08;HPC&#xff09;集群。…

憋了个大招_群发版

大家好&#xff0c;我是良许。 憋了个大招&#xff0c;兄弟们&#xff01;我花了两个月的时间&#xff0c;搭建了一个自己的网站啦&#xff5e; 不卖关子&#xff0c;网站链接为&#xff1a; www.lxlinux.net/e/ 网站首页截图如下&#xff1a; 这个网站全部都是关于嵌入式及…

【JavaWeb学习笔记】6 - Tomcat

项目代码 零、在线文档 Apache Tomcat 8 (8.0.53) - Documentation Index WEB开发 1. WEB,在英语中web表示网/网络资源(页面&#xff0c;图片,css,js)意思&#xff0c;它用于表示WEB服务器(主机)供浏览器访问的资源 2. WEB服务器(主机)上供外界访问的Web资源分为: 静态web…

动手学习深度学习-跟李沐学AI-自学笔记(3)

一、深度学习硬件-CPU和GPU 芯片&#xff1a;Intel or AMD 内存&#xff1a;DDR4 显卡&#xff1a;nVidia 芯片可以和GPU与内存通信 GPU不能和内存通信 1. CPU 能算出每一秒能运算的浮点运算数&#xff08;大概0.15左右&#xff09; 1.1 提升CPU利用率 1.1.1 提升缓存…

Vite4、Vue3、Axios 针对请求模块化封装搭配自动化导入(简单易用)

针对请求模块化封装搭配自动化导入&#xff08;简单易用&#xff09; 目标目录目标代码前提步入正题src / utils / index.jssrc /api / index.jssrc /api / request.jssrc /api / service.jssrc /api / utils.jssrc /api / modules / demo.js 自动化配置vite.config.jseslint 校…

2023中医药国际传承传播大会暨中医药图片和非遗艺术展隆重揭幕

由世界针灸学会联合会、中新社国际传播集团、中国新闻图片网、中国民族医药学会、中国针灸学会联合主办的“2023中医药国际传承传播大会”3日在广东省深圳市举办&#xff0c;“中医药国际传承传播图片展”与“非遗艺术展”在大会举办期间开展迎客。会议聚焦非遗健康、非遗传承等…

案例049:基于微信小程序的校园外卖平台设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【vue】点击导航菜单切换局部页面,打开展示默认栏目,页面刷新等问题

非专业前端&#xff0c;局限性较高&#xff0c;有些问题看起来很小&#xff0c;但是初次接触很棘手&#xff0c;需要查找很多博客&#xff0c;内容也很杂。以下只是过程中总结下来的&#xff0c;要解决的就是标题中的三个问题。 这是我需要达成的效果。 1.第一个是进入导航菜单…

LeetCode:2646. 最小化旅行的价格总和(dfs + 树形dp C++、Java)

目录 2646. 最小化旅行的价格总和 题目描述&#xff1a; 实现代码与解析&#xff1a; DFS DP 原理思路&#xff1a; 2646. 最小化旅行的价格总和 题目描述&#xff1a; 现有一棵无向、无根的树&#xff0c;树中有 n 个节点&#xff0c;按从 0 到 n - 1 编号。给你一个整数…

团队git操作流程

项目的开发要求&#xff1a;&#xff08;1&#xff09;项目组厉员代码提交不少于20次 &#xff08;2&#xff09;项目组厉员每天提交不少于20次 &#xff08;3&#xff09;企业项目开发代码的每天的提交一般提交3-5次 &#xff08;4&#xff09;代码仓库的管理 git的基础操作流…

案例042:基于微信小程序的居住证申报系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

OpenCV-python numpy和基本作图

文章目录 一、实验目的二、实验内容三、实验过程Numpy1.NumPy 操作2.NumPy Ndarray 对象3.NumPy 基本类型4.NumPy 数组属性ndarray.ndimndarray.shapendarray.itemsizendarray.flags 5.NumPy 创建数组numpy.emptynumpy.zerosnumpy.ones 6.NumPy 从已有的数组创建数组numpy.asar…

【Python】Python读Excel文件生成xml文件

目录 ​前言 正文 1.Python基础学习 2.Python读取Excel表格 2.1安装xlrd模块 2.2使用介绍 2.2.1常用单元格中的数据类型 2.2.2 导入模块 2.2.3打开Excel文件读取数据 2.2.4常用函数 2.2.5代码测试 2.2.6 Python操作Excel官方网址 3.Python创建xml文件 3.1 xml语法…

HCL Domino 12系统管理员考试

大家好&#xff0c;才是真的好。 12月份的某一天&#xff0c;趁着风和日丽&#xff0c;天朗气清&#xff0c; 下了舍弃100多美金的狠心&#xff0c;在Pearson Vue官网上报了HCL Domino 12系统管理员考试的名 。时隔十五年后&#xff0c;骑着电动车风风火火地前往某一当地考试中…

AI Pika 生成进击的巨人动漫分镜案例

背景介绍 Pika 是一个使用 AI 生成和编辑视频的平台。它致力于通过 AI 技术使视频制作变得简单和无障碍。 Pika 1.0 是 Pika 的一个重大产品升级&#xff0c;包含了一个新的 AI 模型,可以在各种风格下生成和编辑视频,如 3D 动画&#xff0c;动漫&#xff0c;卡通和电影风格。…