Java-多人聊天小程序

上图啦!!!

结构
首先运行:
Server.java

然后启动:
Client.java

在这里插入图片描述

最后退出客户端:

在这里插入图片描述

代码实现

Client

package chat;import javax.swing.*;public class Client {public static void main(String[] args) {// 使用Windows的界面风格try {UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");} catch (Exception e) {e.printStackTrace();}new TCPClient().start();}
}

Server

package chat;import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;public class Server implements ActionListener {private static final int SERVER_PORT = 2222;private ServerSocket server;private JFrame frame;private JPanel panel;private JTextArea textArea;private JScrollPane scrollPane;private JTextField textField;private JButton button;private boolean isStarted = false; // 服务器是否启动private List<ChatroomClient> clients = new ArrayList<ChatroomClient>();public Server() {frame = new JFrame("服务器");panel = new JPanel();textArea = new JTextArea();textArea.setEditable(false);textArea.setLineWrap(true);scrollPane = new JScrollPane(textArea);scrollPane.setBounds(5, 5, 275, 290);scrollPane.setBorder(BorderFactory.createLoweredSoftBevelBorder());textField = new JTextField();textField.setBounds(6, 305, 210, 30);button = new JButton("发送");button.setBounds(220, 305, 60, 30);button.addActionListener(this);textField.addActionListener(this);panel.add(scrollPane);panel.add(textField);panel.add(button);panel.setLayout(null);frame.add(panel);frame.setSize(300, 400);frame.setLocation((1366 - 640) >> 1, (768 - 400) >> 1);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}public static void main(String[] args) {// 使用Windows的界面风格try {UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");} catch (Exception e) {e.printStackTrace();}new Server().serverStart();}public void serverStart() {while (!isStarted) { // 无限循环尝试启动服务器try {server = new ServerSocket(SERVER_PORT);isStarted = true;Thread.sleep(500);} catch (BindException e) {textArea.setText("端口2222被占用,请关闭对应的程序!\n");} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}textArea.append("服务器启动,等待客户端连接……\n");try {// 无限循环检测是否有客户端加入,有则加到listwhile (isStarted) {Socket s = server.accept();ChatroomClient client = new ChatroomClient(s);clients.add(client);client.start();}} catch (IOException e) {e.printStackTrace();} finally {try {server.close();} catch (IOException e) {e.printStackTrace();}}}// 服务器发送消息public void send() {if (textField.getText().length() < 1) { // 没有输入东西return;} else if (clients.size() == 0) {textArea.append("无客户端连接!\n");return;}SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String s = "服务器    " + dateFormat.format(new Date()) + "\n    " + textField.getText() + "\n";textArea.append(s);// 循环给列表中的客户端发送信息for (int i = 0; i < clients.size(); ++i) {ChatroomClient client = clients.get(i);client.send(s);}textField.setText(null);}public void actionPerformed(ActionEvent arg0) {send();}// Inner Class ChatroomClientclass ChatroomClient extends Thread {private Socket client;private DataInputStream in;private DataOutputStream out;//private boolean isConnected = false;// 客户端初始化public ChatroomClient(Socket client) {this.client = client;try {in = new DataInputStream(client.getInputStream());out = new DataOutputStream(client.getOutputStream());} catch (IOException e) {e.printStackTrace();}SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");textArea.append("客户端已连接  " + dateFormat.format(new Date()) + "\n");textArea.append("地址:" + client.getInetAddress().getHostAddress() + "\n端口:" + client.getPort() + "\n\n");}// 发送消息public void send(String str) {try {out.writeUTF(str);out.flush();} catch (IOException e) {clients.remove(this);textArea.append("客户端已退出,从列表删除!\n");}}public void run() {try {while (true) {textArea.setCaretPosition(textArea.getDocument().getLength()); // 显示JTextArea最末String str = in.readUTF();//str = str.substring(0, 3) + (clients.indexOf(this) + 1) + str.substring(3);textArea.append(str);for (int i = 0; i < clients.size(); ++i) {ChatroomClient client = clients.get(i);client.send(str);}Thread.sleep(100); // 每100ms读取对方信息一次}} catch (IOException e) {textArea.append("客户端断开连接!\n");clients.remove(this);} catch (InterruptedException e) {e.printStackTrace();} finally {clients.remove(this);try {if (in != null)client.close();if (out != null)client.close();if (client != null)client.close();} catch (IOException e) {e.printStackTrace();	}	}	}	}	}

TCPClient

package chat;import java.awt.Color;
import java.awt.event.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;class TCPClient extends Thread implements ActionListener, MouseListener {private String des = "127.0.0.1"; // 服务器地址private int port = 2222; // 服务器端口private Socket client;private DataInputStream in;private DataOutputStream out;private JFrame frame;private JPanel panel;private JTextArea textArea;private JScrollPane scrollPane;private JTextField textField;private JTextField tfDes, tfPort;private JLabel label1, label2, addrChange;private JButton button;private boolean isConnected = false; // 是否连接上public TCPClient() {frame = new JFrame("客户端");panel = new JPanel();textArea = new JTextArea();textArea.setEditable(false);textArea.setLineWrap(true);scrollPane = new JScrollPane(textArea);scrollPane.setBounds(5, 5, 275, 290);scrollPane.setBorder(BorderFactory.createLoweredSoftBevelBorder());textField = new JTextField();textField.setBounds(6, 305, 210, 30);textField.addActionListener(this);button = new JButton("发送");button.setBounds(220, 305, 60, 30);button.addActionListener(this);label1 = new JLabel("服务器地址:");label1.setBounds(10, 340, 75, 20);tfDes = new JTextField(des);tfDes.setBounds(75, 341, 80, 20);tfDes.setBorder(null);label2 = new JLabel("端口:");label2.setBounds(160, 340, 40, 20);tfPort = new JTextField(Integer.toString(port));tfPort.setBounds(190, 341, 35, 20);tfPort.setBorder(null);addrChange = new JLabel("连接");addrChange.setForeground(Color.BLUE);addrChange.setBounds(235, 337, 30, 20);addrChange.setBorder(BorderFactory.createRaisedBevelBorder());addrChange.addMouseListener(this);panel.add(scrollPane);panel.add(textField);panel.add(button);panel.add(label1);panel.add(tfDes);panel.add(label2);panel.add(tfPort);panel.add(addrChange);panel.setLayout(null);frame.add(panel);frame.setSize(300, 400);frame.setLocation(1366 >> 1, (768 - 400) >> 1);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}// 发送消息public void send() {if (textField.getText().length() < 1) { // 没有输入东西return;} else if (out == null || client.isClosed()) {textArea.append("没有与服务器连接!\n");return;}try {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");out.writeUTF(InetAddress.getLocalHost().getHostName() + "    " + dateFormat.format(new Date()) + "\n    " + textField.getText() + "\n");out.flush();//textArea.append("客户端    " + new Date().toLocaleString() + "\n    " + textField.getText() + "\n");textField.setText(null);} catch (IOException e) {e.printStackTrace();}}public void actionPerformed(ActionEvent arg0) {send();}public void mouseClicked(MouseEvent arg0) {}public void mouseEntered(MouseEvent arg0) {}public void mouseExited(MouseEvent arg0) {}public void mousePressed(MouseEvent arg0) {addrChange.setBorder(BorderFactory.createLoweredBevelBorder());}public void mouseReleased(MouseEvent arg0) {addrChange.setBorder(BorderFactory.createRaisedBevelBorder());if (!tfDes.getText().matches("([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}")|| !tfPort.getText().matches("[0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]")) {textArea.append("请输入正确的地址和端口!!\n");return;}String tmpd = tfDes.getText();int tmpp = Integer.parseInt(tfPort.getText());if (des.equals(tmpd) && port == tmpp) {if (isConnected == true)textArea.append("已经和指定服务器连上,请不要重复连接!\n");return;}des = tmpd;port = tmpp;try {if (in != null)in.close();if (out != null)out.close();if (client != null)client.close();} catch (IOException e) {e.printStackTrace();}if (isConnected == false) {textArea.append("正在连接服务器……\n");textArea.append("目标地址:" + des + "\n");textArea.append("目标端口:" + port + "\n");} else {textArea.append("用户中断当前连接!\n");}isConnected = false;}public void run() {while (true) {textArea.append("正在连接服务器……\n");textArea.append("目标地址:" + des + "\n");textArea.append("目标端口:" + port + "\n");while (!isConnected) {try {client = new Socket(des, port);in = new DataInputStream(client.getInputStream());out = new DataOutputStream(client.getOutputStream());isConnected = true;Thread.sleep(500);} catch (IOException e) {continue;} catch (InterruptedException e) {e.printStackTrace();}}SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");textArea.append("连接服务器成功!" + dateFormat.format(new Date()) + "\n\n");try {while (isConnected) {textArea.setCaretPosition(textArea.getDocument().getLength()); // 显示JTextArea最末textArea.append(in.readUTF()); // 每100ms读取对方信息一次Thread.sleep(100);}} catch (IOException e) {textArea.append("与服务器失去连接!\n\n");} catch (InterruptedException e) {e.printStackTrace();} finally {try {if (in != null)in.close();if (out != null)out.close();if (client != null)client.close();} catch (IOException e) {e.printStackTrace();}isConnected = false;}}}}

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

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

相关文章

7步搞懂手写数字识别Mnist

大家好啊&#xff0c;我是董董灿。 图像识别有很多入门项目&#xff0c;其中Mnist 手写数字识别绝对是最受欢迎的。 该项目以数据集小、神经网络简单、任务简单为优势&#xff0c;并且集合了CNN网络中该有的东西&#xff0c;可谓麻雀虽小&#xff0c;五脏俱全。 非常适合新手…

二开项目权限应用全流程-按钮级控制

二开项目权限应用全流程-按钮级控制 员工A和员工B都可以访问同一个页面&#xff08;以员工管理为例&#xff09;&#xff0c;但是员工A可以导出excel&#xff0c;员工B就不可以导出excel(看不到按钮) 思路 用户登陆成功后&#xff0c;用户可以访问的按钮级别权限保存在point…

VISIO使用技巧汇总

0.连接线拐弯或者连接不合适 0-0.Goal ​​​​​​​ 0-1. Automatic connection 0-3.Resolvent 0-3-0.ALTF9选项&#xff0c;取消粘附位置调整 0-3-1.选中线段-选中中心点-shift增加直角调整合适位置

Microsoft Visio 直线连接线

Microsoft Visio 直线连接线 1. 连接线 2. 直线连接线 3. 直线连接线图 References https://yongqiang.blog.csdn.net/

visio画太极图

步骤一 添加两个圆&#xff0c;且大圆的半径是小圆的2倍。 步骤二 往小圆添加一条直线作为直径 步骤三 选中小圆和直径,依次点击开发工具–操作–连接&#xff0c;然后选中连接后的小圆&#xff0c;再依次点击开发工具–操作–修建&#xff0c;可以分离出如下所示的两个…

visio 2007 画直线和矩形

visio 2007 画直线和矩形 1.问题描述 在一些图形中如果直接用连接线&#xff0c;会直接连到一些不理想的位置&#xff0c;而2007中不像2013及其以后那些版本中&#xff0c;有侧边栏能够直接画直线。 2.解决方式 直接选择工具栏中的红圈中的图标 能够生成红圈中的工具栏 然…

Visio对mysql怎么画er图_怎么用Visio画ER图

展开全部 画法如下&#xff1a; 1、由于Visio 2003默认的绘图模板并没有32313133353236313431303231363533e4b893e5b19e31333339653661E-R图这一项&#xff0c;但是画E-R图必须的基本图形Visio 2003还是有的&#xff0c;所以就得先把必要的图形添加到“我的模板”。以添加椭圆和…

Visio2010中设置线为直线

Visio2010中设置线为直线 在Visio2010中默认的线不是直线而是曲线&#xff0c;在画图中需要使用直线时要进行设置&#xff0c;下面介绍Visio2010中设置直线的方法。 1、打开Visio2010&#xff0c;然后点击设计&#xff1a; 2、点击调整大小下面的三角&#xff1a; 3、进入页面…

visio绘制流程图连接线总拐弯

描述 如图所示绘制流程图的连接线总拐弯 很让我强迫症发作 可以看到垂直的连接线总是会自动拐个弯 相关技巧 有说连接线中间点可以控制和增加中间点 或者按住shift 进行调整 这个还没研究明白咋操作不过没解决本质问题 此外还可以右键修改连接线属性 还可以在设计中进行调…

visio插入箭头_visio流程图中画箭头

visio流程图中画箭头 随着社会和经济的发展,电脑visio 2019软件已经成为我们生活中必不可少的一部分。visio 2019软件常常被我们使用于流程图的制作,很多第一次接触的朋友们不知道怎么在visio 2019软件制作流程图,接下来就让小编来教你们吧。 具体如下: 1. 第一步,打开电脑…

visio绘图小技巧

1.如何在图框的任意位置添加点&#xff1f; 先选中x点指令&#xff0c;再按住ctrl键&#xff0c;即可在任意位置画点 2.如何画出锯齿形线段&#xff1f; visio里面好像没有现成的锯齿形线段&#xff0c;所以可以利用直线反复折画&#xff0c;但是这里有个小技巧&#xff0c;就…

Visio简单画图使用方法

Visio使用方法 相信有很多初学者跟我一样&#xff0c;只会使用Word进行简单的画图。本章主要讲述如何使用Visio来画图&#xff08;版本为2010&#xff09; 一、系统流程图、数据流程图、ER图画法 1.打开Visio软件&#xff0c;创建简单模板 2.根据需求点击左侧"基本流程…

设计模式之~外观模式

定义&#xff1a; 为子系统中的一组接口提供一个一致的界面&#xff0c;此模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。 结构图&#xff1a; 区分中介模式&#xff1a; 门面模式对外提供一个接口 中介模式对内提供一个接口 优点&#xff1a; 松耦…

【xv6操作系统】安装、运行与调试

一、构建、装入过程 1.编写“启动代码主体代码”&#xff08;在下载的xv6的原始代码上进行修改&#xff09; 2.源代码进行编译、链接生成系统镜像&#xff08;elf格式的目标文件&#xff09; 3.将系统镜像保存起来&#xff08;如保存到磁盘、flash或者网络服务器上&#xff…

spring入门(面试题)

Spring框架的核心&#xff1a;IoC容器和AOP模块。通过IoC容器管理POJO对象以及他们之间的耦合关系&#xff1b;通过AOP以动态非侵入的方式增强服务。 IoC让相互协作的组件保持松散的耦合&#xff0c;而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。 IO…

spring 入门

Spring 是什么(1) Spring 是一个开源框架.  Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能.  Spring 是一个 IOC(DI) 和 AOP 容器框架. Spring 是什么(2) 具体描述 Spring:  轻量级&#xff1a;Spring 是非侵入性…

spring入门--spring入门案例

spring是一个框架&#xff0c;这个框架可以干很多很多的事情。感觉特别吊。但是&#xff0c;对于初学者来说&#xff0c;很难理解spring到底是干什么的。我刚开始的时候也不懂&#xff0c;后来就跟着敲&#xff0c;在后来虽然懂了&#xff0c;但是依然说不明白它到底是干啥的。…

Spring入门示例

开发环境 Spring 4.3.0Myeclipse2015JDK1.8 准备阶段&#xff1a; 1、新建一Spring01项目&#xff0c;然后新建一个lib文件。将下面的添加到lib文件中 2、将lib文件所有的包导入项目 开发步骤&#xff1a; 1、新建一个Hello.java的类 1 package com.proc.bean;2 3 public class…

Spring入门详解

准备开始看看Spring源码&#xff0c; 所以把Spring复习一遍&#xff0c;做下笔记.. 一. Spring的4种关键策略&#xff1a; 1. 基于POJO的轻量级和最小入侵编程(基本不出现在业务逻辑中&#xff0c; 不用强制实现接口之类的)&#xff1b; 2. 通过依赖注入和面向接口来实现松耦…

1.Spring入门

一、Spring入门 1.Spring 入门 Spring 整体框架&#xff1a; 什么是IOC&#xff1f; IOC&#xff1a;Inversion of Control&#xff08;控制反转&#xff09;&#xff0c;即将对象的创建权反转给&#xff08;交给&#xff09;spring。 spring包含的文件&#xff1a; docs&am…