java聊天室源代码(练习项目)

article/2025/10/23 5:20:06

聊天室界面如下:



聊天室源代码链接

一、服务端:

窗体:

package sonyi.server;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;public class WindowServer {public static JFrame window;public static JTextArea textMessage;//聊天记录public static JList<String> user;//用户列表public static int ports;JButton start,send,exit;JTextField portServer,message,name;//主函数入口public static void main(String[] args) {new WindowServer();}//初始化窗体public WindowServer() {init();}//初始化内容public void init(){//采用绝对布局window = new JFrame("服务端");window.setLayout(null);window.setBounds(200, 200, 500, 400);window.setResizable(false);//不可改变大小JLabel label1 = new JLabel("端口号:");label1.setBounds(10, 8, 50, 30);window.add(label1);portServer = new JTextField();portServer.setBounds(60, 8, 100, 30);portServer.setText("30000");window.add(portServer);JLabel names = new JLabel("用户名:");names.setBounds(180, 8, 55, 30);window.add(names);name = new JTextField();name.setBounds(230, 8, 60, 30);name.setText("服务端");window.add(name);start = new JButton("启动");start.setBounds(300, 8, 80, 30);window.add(start);exit = new JButton("关闭");exit.setBounds(390, 8, 80, 30);window.add(exit);JLabel label2 = new JLabel("用户列表");label2.setBounds(40, 40, 80, 30);window.add(label2);user = new JList<String>();JScrollPane scrollPane = new JScrollPane(user);//添加滚动条scrollPane.setBounds(10, 70, 120, 220);window.add(scrollPane);textMessage = new JTextArea();textMessage.setBounds(135, 70, 340, 220);textMessage.setBorder(new TitledBorder("聊天记录"));//设置标题textMessage.setEditable(false);//不可编辑//文本内容换行的两个需要配合着用textMessage.setLineWrap(true);//设置文本内容自动换行,在超出文本区域时,可能会切断单词textMessage.setWrapStyleWord(true);//设置以自动换行,以单词为整体,保证单词不会被切断JScrollPane scrollPane1 = new JScrollPane(textMessage);//设置滚动条scrollPane1.setBounds(135, 70, 340, 220);window.add(scrollPane1);message = new JTextField();message.setBounds(10, 300, 360, 50);window.add(message);send = new JButton("发送");send.setBounds(380, 305, 70, 40);window.add(send);myEvent();	//添加监听事件window.setVisible(true);}public void myEvent(){window.addWindowListener(new WindowAdapter() {//关闭窗体public void windowClosing(WindowEvent e){//如果有客户端存在,发信息给客户端,并退出if(StartServer.userList != null && StartServer.userList.size() != 0){try {new SendServer(StartServer.userList, "" , "4");//4代表服务端退出} catch (IOException e1) {e1.printStackTrace();}}System.exit(0);//退出窗体}});exit.addActionListener(new ActionListener() {	//退出连接public void actionPerformed(ActionEvent e) {if(StartServer.ss == null || StartServer.ss.isClosed()){//如果已退出,弹窗提醒JOptionPane.showMessageDialog(window, "服务器已关闭");}else {//发信息告诉客户端,要退出if(StartServer.userList != null && StartServer.userList.size() != 0){try {new SendServer(StartServer.userList, "" , 4 + "");	} catch (IOException e1) {e1.printStackTrace();}}try {start.setText("启动");exit.setText("已关闭");StartServer.ss.close();//关闭服务端StartServer.ss = null;StartServer.userList = null;StartServer.flag = false;//改变服务端循环标记} catch (IOException e1) {e1.printStackTrace();}}	}});//开启服务端start.addActionListener(new ActionListener() {		public void actionPerformed(ActionEvent e) {//如果服务端已经开启,弹窗提醒服务端已开启if(StartServer.ss != null && !StartServer.ss.isClosed()){JOptionPane.showMessageDialog(window, "服务器已经启动");}else {ports = getPort();//获取端口号if(ports != 0){try {StartServer.flag = true;//改变服务端接收循环标记new Thread(new StartServer(ports)).start(); //开启服务端接收线程start.setText("已启动");exit.setText("关闭");} catch (IOException e1) {JOptionPane.showMessageDialog(window, "启动失败");}}}}});//点击按钮发送消息send.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {sendMsg();}});//按回车发送消息message.addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent e) {if(e.getKeyCode() == KeyEvent.VK_ENTER){sendMsg();}}});}//发送消息方法public void sendMsg(){String messages = message.getText();//判断内容是否为空if("".equals(messages)){JOptionPane.showMessageDialog(window, "内容不能为空!");}else if(StartServer.userList == null || StartServer.userList.size() == 0){//判断是否已经连接成功JOptionPane.showMessageDialog(window, "未连接成功,不能发送消息!");}else {try {//将信息发送给所有客户端new SendServer(StartServer.userList, getName() + ":" + messages, 1 + "");//将信息添加到客户端聊天记录中WindowServer.textMessage.append(getName() + ":" + messages + "\r\n");message.setText(null);//消息框设置为空} catch (IOException e1) {JOptionPane.showMessageDialog(window, "发送失败!");}}}//获取端口号public int getPort(){String port = portServer.getText();if("".equals(port)){//判断端口号是否为空JOptionPane.showMessageDialog(window, "端口号为口");return 0;}else {return Integer.parseInt(port);//返回整形的端口号}	}	//获取服务端名称public String getName(){return name.getText();}
}

发送接收线程:

package sonyi.server;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Vector;import javax.swing.JOptionPane;//启动服务端接收客户端的线程
public class StartServer implements Runnable{private int port;public static ArrayList<Socket> userList = null;public static Vector<String> userName = null;public static ServerSocket ss = null;public static boolean flag = true;//传入端口号public StartServer(int port) throws IOException{this.port = port;		}public void run() {Socket s = null;userList = new ArrayList<Socket>();//客户端端口容器userName = new Vector<String>();//用户名称容器//System.out.println("启动服务端");try {ss = new ServerSocket(port);//启动服务端} catch (IOException e1) {e1.printStackTrace();}while (flag) {//开启循环,等待接收客户端try {	s = ss.accept();//接收客户端userList.add(s);//将客户端的socket添加到容器中//打印客户端信息String id = s.getInetAddress().getHostName();System.out.println(id + "-----------connected");System.out.println("当前客户端个数为:" + userList.size());//启动与客户端相对应的信息接收线程new Thread(new ReceiveServer(s,userList,userName)).start();} catch (IOException e) {JOptionPane.showMessageDialog(WindowServer.window, "服务端退出!");}	}}
}//服务端信息接收线程
class ReceiveServer implements Runnable{private Socket socket;private ArrayList<Socket> userList;private Vector<String> userName;public ReceiveServer(Socket s,ArrayList<Socket> userList,Vector<String> userName) {this.socket = s;this.userList = userList;this.userName = userName;}public void run() {	try {//读取信息流BufferedReader brIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));while(true){		char info = (char)brIn.read();//先读取信息流的首字符,并判断信息类型String line = brIn.readLine();//读取信息流的信息内容if(info == '1'){//1代表收到的是信息WindowServer.textMessage.append(line + "\r\n");//将信息添加到服务端聊天记录中//设置消息显示最新一行,也就是滚动条出现在末尾,显示最新一条输入的信息WindowServer.textMessage.setCaretPosition(WindowServer.textMessage.getText().length());new SendServer(userList, line, "1");//将信息转发给客户端}if(info == '2'){//2代表有新客户端建立连接userName.add(line);//将新客户端用户名添加到容器中WindowServer.user.setListData(userName);//更新服务端用户列表new SendServer(userList, userName, "2");//将用户列表以字符串的形式发给客户端}if(info == '3'){//3代表有用户端退出连接userName.remove(line);//移除容器中已退出的客户端用户名userList.remove(socket);//移除容器中已退出的客户端的socketWindowServer.user.setListData(userName);//更新服务端用户列表new SendServer(userList, userName, "3");//将用户列表以字符串的形式发给客户端socket.close();//关闭该客户端的socketbreak;//结束该客户端对于的信息接收线程}}	} catch (IOException e) {e.printStackTrace();}}	
}//服务端发送信息
class SendServer {SendServer(ArrayList<Socket> userList,Object message,String info) throws IOException{String messages = info + message;//添加信息头标记PrintWriter pwOut = null;for(Socket s : userList){//将信息发送给每个客户端pwOut = new PrintWriter(s.getOutputStream(),true);pwOut.println(messages);}}
}	

二、客户端:

窗体:

package sonyi.client;import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;public class WindowClient {JTextField port,name,ip,message;JButton send;public static JFrame window;public static JButton link,exit;public static JTextArea textMessage;public static Socket socket = null;public static JList<String> user;//主函数入口public static void main(String[] args) {new WindowClient();}//初始化窗体public WindowClient() {init();}//窗体初始化内容public void init(){//采用绝对布局window = new JFrame("客户端");window.setLayout(null);window.setBounds(200, 200, 500, 400);window.setResizable(false);JLabel label = new JLabel("主机IP:");label.setBounds(10, 8, 50, 30);window.add(label);ip = new JTextField();ip.setBounds(55, 8, 60, 30);ip.setText("127.0.0.1");window.add(ip);JLabel label1 = new JLabel("端口号:");label1.setBounds(125, 8, 50, 30);window.add(label1);port = new JTextField();port.setBounds(170, 8, 40, 30);port.setText("30000");window.add(port);JLabel names = new JLabel("用户名:");names.setBounds(220, 8, 55, 30);window.add(names);name = new JTextField();name.setBounds(265, 8, 60, 30);name.setText("客户端1");window.add(name);link = new JButton("连接");link.setBounds(335, 8, 75, 30);window.add(link);exit = new JButton("退出");exit.setBounds(415, 8, 75, 30);window.add(exit);JLabel label2 = new JLabel("用户列表");label2.setBounds(40, 40, 80, 30);window.add(label2);user = new JList<String>();JScrollPane scrollPane = new JScrollPane(user);//设置滚动条scrollPane.setBounds(10, 70, 120, 220);window.add(scrollPane);textMessage = new JTextArea();textMessage.setBounds(135, 70, 340, 220);textMessage.setEditable(false);//文本不可编辑textMessage.setBorder(new TitledBorder("聊天记录"));//设置标题//文本内容换行的两个需要配合着用textMessage.setLineWrap(true);//设置文本内容自动换行,在超出文本区域时,可能会切断单词textMessage.setWrapStyleWord(true);//设置以自动换行,以单词为整体,保证单词不会被切断JScrollPane scrollPane1 = new JScrollPane(textMessage);//设置滚动条scrollPane1.setBounds(135, 70, 340, 220);window.add(scrollPane1);message = new JTextField();message.setBounds(10, 300, 360, 50);message.setText(null);window.add(message);send = new JButton("发送");send.setBounds(380, 305, 70, 40);window.add(send);myEvent();//添加监听事件window.setVisible(true);//设置窗体可见	}public void myEvent(){//事件监听window.addWindowListener(new WindowAdapter() {//退出窗体public void windowClosing(WindowEvent e){//如果仍在连接,发信息给服务端,并退出if(socket != null && socket.isConnected()){try {new SendClient(socket, getName(), 3 + "");} catch (IOException e1) {e1.printStackTrace();}}System.exit(0);}});//关闭连接exit.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {//如果仍在连接,将信息发给服务端if(socket == null){JOptionPane.showMessageDialog(window, "已关闭连接");}else if(socket != null && socket.isConnected()){try {new SendClient(socket, getName(), "3");//发送信息给服务端link.setText("连接");exit.setText("已退出");socket.close();//关闭socketsocket = null;} catch (IOException e1) {e1.printStackTrace();}}}});//建立连接link.addActionListener(new ActionListener() {		public void actionPerformed(ActionEvent e) {//判断是否已经连接成功if(socket != null && socket.isConnected()){	JOptionPane.showMessageDialog(window, "已经连接成功!");}else {String ipString = ip.getText();//获取ip地址String portClinet = port.getText();//获取端口号if("".equals(ipString) || "".equals(portClinet)){//判断获取内容是否为空JOptionPane.showMessageDialog(window, "ip或端口号为空!");}else {try {int ports = Integer.parseInt(portClinet);//将端口号转为整形socket = new Socket(ipString,ports);//建立连接link.setText("已连接");//更改button显示信息exit.setText("退出");new SendClient(socket, getName(), 2 + "");//发送该客户端名称至服务器new Thread(new ReceiveClient(socket)).start();//启动接收线程} catch (Exception e2) {JOptionPane.showMessageDialog(window, "连接未成功!可能是ip或端口号格式不对,或服务器未开启。");}}}}});//点击按钮发送信息send.addActionListener(new ActionListener() {			public void actionPerformed(ActionEvent e) {sendMsg();}});	//按回车发送信息message.addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent e) {if(e.getKeyCode() == KeyEvent.VK_ENTER){sendMsg();}}});}//发送信息的方法public void sendMsg(){String messages = message.getText();//获取文本框内容if("".equals(messages)){//判断信息是否为空JOptionPane.showMessageDialog(window, "内容不能为空!");}else if(socket == null || !socket.isConnected()){//判断是否已经连接成功JOptionPane.showMessageDialog(window, "未连接成功,不能发送消息!");}else {try {//发送信息new SendClient(socket,getName() + ":" + messages,"1");message.setText(null);//文本框内容设置为空} catch (IOException e1) {JOptionPane.showMessageDialog(window, "信息发送失败!");}}	}//获取客户端名称public String getName(){return name.getText();}
}

发送接收线程:

package sonyi.client;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;import javax.swing.JOptionPane;//启动客户端接收线程
public class StartClient {public StartClient(Socket s) throws UnknownHostException, IOException{	new Thread(new ReceiveClient(s)).start();}
}//客户端接收线程
class ReceiveClient implements Runnable{private Socket s;public ReceiveClient(Socket s) {this.s = s;}public void run() {try {//信息接收流BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));while(true){	char info = (char)brIn.read();//读取信息流首字符,判断信息类型String line = brIn.readLine();//读取信息流内容if(info == '1'){//代表发送的是消息WindowClient.textMessage.append(line + "\r\n");	//将消息添加到文本域中//设置消息显示最新一行,也就是滚动条出现在末尾,显示最新一条输入的信息WindowClient.textMessage.setCaretPosition(WindowClient.textMessage.getText().length());}if(info == '2' || info == '3'){//有新用户加入或退出,2为加入,3为退出String sub = line.substring(1, line.length()-1);String[] data = sub.split(",");WindowClient.user.clearSelection();WindowClient.user.setListData(data);}if(info == '4'){//4代表服务端退出WindowClient.link.setText("连接");WindowClient.exit.setText("已退出");WindowClient.socket.close();WindowClient.socket = null;break;}}	} catch (IOException e) {JOptionPane.showMessageDialog(WindowClient.window, "客户端已退出连接");}}	
}//客户端发送信息类
class SendClient {SendClient(Socket s,Object message,String info) throws IOException{	String messages = info + message;PrintWriter pwOut = new PrintWriter(s.getOutputStream(),true);pwOut.println(messages);}
}	

运行过程中应该还有很多bug,希望码友们指正,互相交流。




http://chatgpt.dhexx.cn/article/6ZRAH4Vn.shtml

相关文章

Java—简易聊天室

Java—聊天室的实现 在学习了IO流&#xff0c;多线程以及网络编程的知识之后&#xff0c;我们可以利用所学到的知识做一个小项目&#xff0c;这里我做了一个多人聊天室&#xff0c;实现了群聊和私聊功能&#xff0c;看完分享之后也可以自己去做一个练练手。 首先是整个项目的…

java聊天室(实训项目)

这里是我们实训的一个关于java聊天室的项目&#xff0c;有需要的同学可以看看&#xff0c;私聊功能未完善。 话不多说&#xff0c;直接上代码。 服务器&#xff1a; package ChatRoom;import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; impor…

Java实现简易聊天室

Java实现简易聊天室 在学习《Java从入门到精通》这本书&#xff0c;网络通信&#xff0c;基于TCP实现的简易聊天室&#xff0c;我这里对书中的代码略做了修改&#xff0c;做个记录。 这里先放一下运行效果图&#xff0c;代码放在最后。 运行效果&#xff1a; 先启动服务器端&am…

javaWeb实现聊天室(私聊+群聊)

写在前面 近几天&#xff0c;迎来了第一个小项目&#xff0c;不做不知道&#xff0c;一做吓一跳。好多知识都掌握的不够扎实&#xff0c;看似会了&#xff0c;但其实似懂非懂&#xff0c;不能真正掌握原理&#xff0c;导致使用起来错误百出。而且深深体会到&#xff0c;知识只有…

java实现聊天室(GUI界面+私聊+群聊)

登录界面的用户名和端口号不能重复&#xff01; 登录界面的用户名和端口号不能重复&#xff01; 登录界面的用户名和端口号不能重复&#xff01; java的socket编写的聊天室&#xff0c;GUI的界面&#xff0c;可以私聊和群聊&#xff0c; 聊天信息保存为txt 有需要的可以自行下…

用Java代码实现一个简单的聊天室功能

一.客户端的创建 1.我们可以用Socket来创建客户端 /***类名 Client*描述 TODO 客户端 1*版本 1.0*创建人 XuKang*创建时间 2020/9/24 16:18**/ public class Client {public static void main(String[] args) throws UnknownHostException, IOException {System.out.println(…

Java在线聊天室(客户端+服务器)

Java在线聊天室&#xff08;客户端服务器&#xff09;基于webSocket实现模拟在线聊天系统 运行环境&#xff1a; JDK1.8version 开发环境&#xff1a;Eclipse 一、结构 以下是系统主要结构&#xff1a; 1.用户&#xff08;均实现部分可能会有bug&#xff09; &#xff08;…

apiDay09整理笔记(笔记优化)

目录 1.聊天室&#xff08;续&#xff09; &#xff08;1&#xff09;实现服务端发送消息给客户端 &#xff08;2&#xff09;服务端转发消息给所有客户端 &#xff08;3&#xff09;客户端解决收发消息的冲突问题 &#xff08;4&#xff09;服务端完成处理客户端断开连接…

JAVA简单聊天室的实现

目录 界面效果图 一、聊天室功能介绍&#xff1f; 二、功能代码 1.服务端 2.客户端 界面效果图 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、聊天室功能介绍&#xff1f; 1. 、对于聊天室就是处理多个客户端发送的请求与信息&#xff0c;从…

Java网络聊天室---个人博客

Java网络聊天室 ———个人博客 一、项目简介 功能描述&#xff1a; 使用图形用户界面和socket通信&#xff0c;能实现一个聊天室中多人聊天&#xff0c;可以两人私聊&#xff0c;可以发送文件。 实现类似QQ用户注册、登录、聊天等功能。 参考git地址或博客地址&#xff1a…

Java实现ChatRoom

基于连接通信Socket、多线程的Java聊天室 1、开发环境&#xff1a; IDEA2018.1JDK1.8 2、实现功能&#xff1a; 实现了模拟登录注册、群聊、私聊、显示当前在线人数列表&#xff1b; 在发送信息时&#xff0c;会向对方发送者及显示发送时间&#xff1b; 显示在线人数列表…

Java聊天室

项目介绍&#xff1a; Java聊天室是期末设计&#xff0c; 阿里巴巴druidmysql多线程GUImvn项目java Socket 服务端模块&#xff1a;踢出聊天室&#xff1a;管理员可以踢出发言不当的用户。只有当开启服务端的时候&#xff0c;客户端才能起到作用。 客户端模块&#xff1a; 注册…

用Java实现简易聊天室

说明&#xff1a;如果一个 类&#xff0c;需要有界面的显示&#xff0c;那么该类就需要继承自JFrame&#xff0c;此时&#xff0c;该类就可以被称为一个“窗体类"。 服务端代码&#xff1a; package cn.qy.chat;import javax.swing.*; import java.awt.*; import java.aw…

微信小程序购物车功能实现(干货满满)

微信小程序定制好看的购物车页面&#xff0c;实现购物车功能&#xff0c;希望对您有所帮助&#xff01; 1. 应用场景 2. 思路分析 3. 代码分析 4. 具体实现代码 效果截图&#xff1a; 1.应用场景 适用于商城、秒杀、商品购买等类型的小程序&#xff0c;负责将顾客浏览的商…

微信小程序微商城(八):缓存实现商品购物车功能

IT实战联盟博客&#xff1a;http://blog.100boot.cn 上一篇&#xff1a;微信小程序微商城&#xff08;七&#xff09;&#xff1a;动态API实现商品分类 看效果 购物车.gif 开发计划 1、商品详情页将商品信息放入缓存 2、购物车页面读取缓存获取商品信息 3、购物车商品计算…

微信小程序开发一个小型商城(六、购物车页面)

上一篇文章&#xff1a;微信小程序开发一个小型商城&#xff08;五、商品详情&#xff09; 当我们在商品详情界面中点击添加购物后&#xff0c;会跳转到购物车界面&#xff0c;购物车界面是一个tabbar&#xff0c;在跳转的时候需要加上ope-type。看下购物车的静态页面把&#x…

微信小程序实现一个购物车页面的简易列表效果

本文只是简单的模仿天猫APP的购物车列表的样式效果&#xff0c;并实现了部分事件功能&#xff0c;功能并不完善&#xff0c;请降低期待观看。 天猫APP的购物车效果&#xff1a; 小程序模仿的实现效果&#xff1a; wxml部分的代码&#xff1a; <view wx:if"{{!isCartEmp…

【Python之pymysql库学习】一、分析fetchone()、fetchmany()、fetchall()(保姆级图文+实现代码)

目录 实现效果实现思路实现代码总结 欢迎关注 『Python之pymysql库学习』 系列&#xff0c;持续更新中 欢迎关注 『Python之pymysql库学习』 系列&#xff0c;持续更新中 实现效果 实现思路 其实有半数代码是创建数据库和创建数据表并插入数据这些环境配置部分我都写好了&…

fetchone、fetchall

fetchone(): 该方法获取下一个查询结果集。结果集是一个对象,读取一行结果&#xff0c;读取完指向下一行&#xff0c;到空为止 fetchall():接收全部的返回结果行&#xff0c;到空为止 fetchone() &#xff1a; 返回单个的元组&#xff0c;也就是一条记录(row)&#xff0c;如果没…

python fetchall方法_Python连接MySQL并使用fetchall()方法过滤特殊字符

python3.3从mysql里取出的数据莫名其妙有括号和逗号每天跟自己喜欢的人一起&#xff0c;通电话&#xff0c;旅行&#xff0c;重复一个承诺和梦想&#xff0c;听他第二十八次提起童年往事&#xff0c;每年的同一天和他庆祝生日&#xff0c;每年的情人节圣诞节除夕&#xff0c;也…