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

news/2024/11/19 13:20:49/

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等 

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

 


http://www.ppmy.cn/news/1260424.html

相关文章

特性【C#】

C#特性是一种用于在编译时向程序元素添加声明性信息的语言结构。 下面是C#特性的使用方法&#xff1a; 1.使用系统提供的特性&#xff1a; 可以使用系统提供的特性来标记类、方法、属性等&#xff0c;以便在编译时进行验证或者提供其他信息。例如&#xff0c;可以使用Obsole…

Ubuntu下应用软件安装

Ubuntu下工具软件安装 一、 输入法安装1.1 搜狗拼音输入法1.2 其它输入法 二、 图片工具安装2.1 截图工具Flameshot2.2 图片编辑工具Ksnip 三、 文字编辑工具3.1 Obsidian 四、录屏工具4.1 Kazam 一、 输入法安装 如果没有输入法&#xff0c;安装其它软件就不好用中文搜索了。…

Qt开发 之 记一次安装 Qt5.12.12 安卓环境的失败案例

文章目录 1、安装Qt2、安卓开发的组合套件2.1、CSDN地址2.2、官网地址2.3、发现老方法不适用了3、尝试用新方法解决3.1、先安装JDK,搞定JDK环境变量3.1.1、安装jdk3.1.2、确定jdk安装路径3.1.3、打开系统环境变量配置3.1.4、配置系统环境变量3.1.5、验证JDK环境变量是否配置成…

与时代共进退

还记得当初自己为什么选择计算机&#xff1f; 当初你问我为什么选择计算机&#xff0c;我笑着回答&#xff1a;“因为我梦想成为神奇的码农&#xff01;我想像编织魔法一样编写程序&#xff0c;创造出炫酷的虚拟世界&#xff01;”谁知道&#xff0c;我刚入门的那天&#xff0…

QT+Unity3D 超详细(将unity3D与QT进行连接,并实现信息传递)

QTUnity3D连接 在QT中连接unity3D&#xff0c;首先要有一个unity.exe执行文件。在这里不提供unity执行文件的编写&#xff0c;只提供QT这边与unity3D连接和信息传递。 创建项目 创建一个新的项目&#xff0c;我创建的项目名称如下。 下图是我建立新项目的文件。APP文件就是…

数据结构:图文详解双向链表的各种操作(头插法,尾插法,任意位置插入,查询节点,删除节点,求链表的长度... ...)

目录 一.双向链表的概念 二.双向链表的数据结构 三.双向链表的实现 节点的插入 头插法 尾插法 任意位置插入 节点的删除 删除链表中第一次出现的目标节点 删除链表中所有与关键字相同的节点 节点的查找 链表的清空 链表的长度 四.模拟实现链表的完整代码 前言&am…

HTTP 基本概念(计算机网络)

一、HTTP 是什么&#xff1f; HTTP(HyperText Transfer Protocol) &#xff1a;超文本传输协议。 HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。 「HTTP 是用于从互联网服务器传输超文本到本地浏览器的协议…

mysql的几种索引

mysql索引的介绍可以mysql官网的词汇表中搜索&#xff1a; https://dev.mysql.com/doc/refman/8.0/en/glossary.html mysql可以在表的一列、或者多列上创建索引&#xff0c;索引的类型可以选择&#xff0c;如下&#xff1a; 普通索引&#xff08;KEY&#xff09; 普通索引可…