当前位置: 首页 > news >正文

使用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() {/*用来对每个客户端发送公告*/@Overridepublic 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方法 来实现对客户端的操作方法*/@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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;}@Overridepublic 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等 

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

 

相关文章:

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

1.整体思路 思路图 整体思路如上: 涉及知识点:线程网络编程集合IO等 TCP 协议 2.代码实现过程 服务端 import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import jav…...

相关教程test

第一天 主题&#xff1a;LLM初体验 上午&#xff1a; 一&#xff0c;大模型的发展背景和模型演进 数据增长和算力提升LSTM到BERT到LLM的参数巨变最新paper解读&#xff08;根据授课时间&#xff0c;选择最近的核心paper进行解读&#xff09; 二&#xff0c;大模型核心阶段…...

mysql知识分享(包含安装卸载)(一)

如果博客有错误&#xff0c;请佬指正。 目录 注意&#xff1a;打开cmd时要有管理员身份打开&#xff0c;重要 为何使用数据库&#xff1f; 数据库的相关概念 关系型数据库 关系型数据库设计规则 表&#xff0c;记录&#xff0c;字段 表的关联关系 一对一关联 一对多关系 …...

Google Guava 反射工具使用详解

文章目录 反射类操作方法操作字段操作获取注解 反射 在 Guava 中&#xff0c;反射&#xff08;Reflection&#xff09;模块提供了一些用于简化反射操作的工具类和方法。通过 Guava 的反射模块&#xff0c;您可以方便地进行类、方法、字段的操作、获取注解信息等。下面详细介绍…...

MySql MVCC 详解

注意以下操作都是以InnoDB引擎为操作基准。 一&#xff0c;前置知识准备 1&#xff0c;MVCC简介 MVCC 是多版本并发控制&#xff08;Multiversion Concurrency Control&#xff09;的缩写。它是一种数据库事务管理技术&#xff0c;用于解决并发访问数据库的问题。MVCC 通过创…...

工业机器视觉megauging(向光有光)使用说明书(三,轻量级的visionpro)

下来我们说说第二个相机的添加&#xff1a; 第一步&#xff0c;点击相机二&#xff0c;如下&#xff1a; 第二步&#xff0c;点击&#xff1a;加载工具组.xml&#xff0c;加载toolgroupxml2目录下的&#xff1a;工具组.xml 注意&#xff0c;一个相机只能用一个toolgroupxml,第…...

Linux 环境下,jdbc连接mysql问题

1. 下载MySQL的JDBC驱动&#xff1a; 从MySQL官网下载最新的MySQL Connector/J&#xff0c;并将其解压到某个目录&#xff0c;比如/usr/local/mysql/。 2. 将JDBC驱动添加到类路径&#xff1a; 将JDBC驱动添加到类路径&#xff0c;可以使用以下命令&#xff1a; export CLA…...

Python读写txt文件数据

&#x1f388; 博主&#xff1a;一只程序猿子 &#x1f388; 博客主页&#xff1a;一只程序猿子 博客主页 &#x1f388; 个人介绍&#xff1a;爱好(bushi)编程&#xff01; &#x1f388; 创作不易&#xff1a;如喜欢麻烦您点个&#x1f44d;或者点个⭐&#xff01; &#x1f…...

Linux虚假唤醒

为什么会有虚假唤醒一说。Linux内核这么强大&#xff0c;怎么会出现这样的情况&#xff1f;一直以来也很困惑&#xff0c;看了下文链接中的介绍后&#xff0c;豁然开朗。 从计算机设计的角度&#xff0c;如果一层解决不了&#xff0c;那就再多加一层。推算到这里&#xff0c;就…...

倒计时模块复习

经典回顾倒计时 倒计时的基本布局介绍。 一个内容区域和一个输入区域&#xff0c;内容区域进行划分 直接使用flex布局会更快一点。 js代码 我们利用一下模块化思想&#xff0c;直接把获得时间这个功能写成一个函数。方便后续的调用 function getTime() {const date new Date…...

k8s(三): 基本概念-ReplicaSet与Deployment

PeplicaSet ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合&#xff0c;通常用来保证给定数量的、完全相同的 Pod 的可用性。 最佳实践 Deployment 是一个可以拥有 ReplicaSet 并使用声明式方式在服务器端完成对 Pod 滚动更新的对象。 尽管 Rep…...

Linux 的介绍和云服务器上web 程序部署

目录 一.linux的介绍 1.1linux是什么 1.2linux的发展历程 1.3linux发行版 二.Linux环境搭建 2.1阿里云-云服务器配置 2.2使用终端软件连接Linux 三.操作Linux&#xff0c;部署web程序 3.1Linux指令 3.2部署web程序 第一步&#xff1a;认识yum 第二步&#xff1a;安装…...

Oauth2.0 学习

OAuth 2.0 服务器端通常通过验证每次请求中的访问令牌&#xff08;access token&#xff09;的方式来确保其合法性和有效性。以下是一些通常采用的验证方法&#xff1a; Token Validation Endpoint: OAuth 2.0 规范允许实现一个专门的令牌验证端点&#xff0c;称为 Token Valid…...

Elasticsearch:什么是向量数据库?

向量数据库定义 向量数据库是将信息存储为向量的数据库&#xff0c;向量是数据对象的数值表示&#xff0c;也称为向量嵌入。 它利用这些向量嵌入的强大功能来对非结构化数据和半结构化数据&#xff08;例如图像、文本或传感器数据&#xff09;的海量数据集进行索引和搜索。 向…...

rename--统一的PRF

基本概念 将ARF/PRF进行合并&#xff0c;合同之后的不见&#xff0c;称之为统一的PRF(Physical Register File);存储的是speculative的&#xff0c;以及正确的&#xff08;retire&#xff09;寄存器值&#xff1b; 使用free list&#xff0c;存储PRF中&#xff0c;哪些寄存器是…...

010-editor破解(1)

查看字符串 使用rabin2 -z /home/burning/010editor/010editor | tee 22.txt 查看字符串。 6698 0x003ba380 0x007ba380 68 69 .rodata ascii The password you entered is for an earlier version of this program. 6699 0x003ba3c8 0x007ba3c8 70 71 .rodata ascii You will…...

Ubuntur编译ROS报错:error PCL requires C++14 or above

ubuntu20.04 编译ROS包 报错&#xff1a; error&#xff1a; PCL requires C14 or above&#xff1a; 修改Cmakelists.txt文件&#xff1a; set&#xff08;CMAKE_CXX_STANDARD 14&#xff09; 再次编译成功....

17.认识下Docker之docker的核心原理(2)

1.容器-我的小世界 不知道大家看没看过小说《完美时间》&#xff0c;里面石昊经常进入一个小世界在里面与世隔绝的修炼或者战斗&#xff0c;总之就是在一个完全封闭的空间里做他想做的事情而与外界隔离&#xff0c;不受侵扰。通过前面的分析我们知道&#xff0c;Namepace让应用…...

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)

文章目录 前言正文一、POM依赖二、核心Java文件2.1 自定义表头注解 ExcelColumnTitle2.2 自定义标题头的映射接口2.3 自定义有序map存储表内数据2.4 表头工厂2.5 表flag和表头映射枚举2.6 测试用的实体2.6.1 NameAndFactoryDemo2.6.2 StudentDemo 2.7 启动类2.8 测试控制器 三、…...

代码随想录算法训练营第四十二天 _ 动态规划_01背包问题、416.分割等和子集。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 二维数组处理01背包问题 听起来…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

ui框架-文件列表展示

ui框架-文件列表展示 介绍 UI框架的文件列表展示组件&#xff0c;可以展示文件夹&#xff0c;支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项&#xff0c;适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...

JavaScript 标签加载

目录 JavaScript 标签加载script 标签的 async 和 defer 属性&#xff0c;分别代表什么&#xff0c;有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...