java实现多人聊天室可视化
作者:丶di 发布时间:2021-08-27 01:16:49
标签:java,聊天室,可视化
编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用”,其中 XXX 是自己的班级姓名学号,如“软件 171 张三 1234”。
客户端
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import java.io.*;
class Login extends JFrame implements ActionListener{
//用户名
JPanel jp1=new JPanel();
JLabel jl1=new JLabel("用户名");
public JTextField jtf1=new JTextField(15);
//密码
JPanel jp2=new JPanel();
JLabel jl2=new JLabel("密码");
JPasswordField jpf2 = new JPasswordField(15);
//登入取消按钮
JPanel jp3=new JPanel();
JButton jbt1=new JButton("登入");
JButton jbt2=new JButton("取消");
public Login() {
// TODO 自动生成的构造函数存根
this.setTitle("客服端登入窗口");
Container con =this.getContentPane();
con.setLayout(new FlowLayout());
//用户名
jp1.add(jl1);
jp1.add(jtf1);
jtf1.addActionListener(this);
//密码
jpf2.setEchoChar('*'); //用*显示密码框输入的数据
jp2.add(jl2);
jp2.add(jpf2);
jpf2.addActionListener(this);
//登入取消按钮
jp3.add(jbt1);
jp3.add(jbt2);
//添加到当前窗口容器
con.add(jp1);
con.add(jp2);
con.add(jp3);
this.setSize(500, 300); //设置窗体大小
setLocationRelativeTo(null); //设置窗口居中
this.setResizable(false); //窗体大小设置为不可改
this.setVisible(true); //窗体设置为可见
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//光标聚焦在用户框中
jtf1.requestFocus();
//为登入按钮添加 *
jbt1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
String name=jtf1.getText();
String password=new String(jpf2.getPassword()); //获取密码框中的密码
try {
if(password.equals("123")) {
setVisible(false);
new Client(jtf1.getText());
}
else {
JOptionPane.showConfirmDialog(null, "用户名或密码错误!",
"提示",JOptionPane.DEFAULT_OPTION);
}
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
});
jbt2.addActionListener(new ActionListener() { //为取消按钮添加 *
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
try {
setVisible(false);
} catch (Exception e2) {
// TODO: handle exception
}
}
});
}
//移动光标聚集
public void actionPerformed(ActionEvent e) {
Object o=e.getSource();
if(o==jtf1) {
jpf2.requestFocus();
}
}
}
public class Client extends JFrame {
public DataOutputStream dos=null;
public DataInputStream dis=null;
public Socket s=null;
public ServerSocket sc=null;
//
public JTextArea jta=new JTextArea(10,20);
public JTextField jtf=new JTextField(20);
public JScrollPane jsp = new JScrollPane(jta);
static final String CONNSTR="127.0.0.1";
public String ClientName="";
//构造函数初始化
Client(String tClientName) throws IOException{
ClientName=tClientName;
this.setTitle("客服端:"+ClientName);
jta.setEditable(false); //文本显示框不可编辑
this.add(jtf,BorderLayout.SOUTH);
this.add(jsp,BorderLayout.CENTER);
//默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//连接服务器
try {
s=new Socket(CONNSTR,9995);
new ThreadClient(s,this).start();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
JOptionPane.showConfirmDialog(null, "用户连接服务器失败",
"提示",JOptionPane.DEFAULT_OPTION);
}
//发送登入信息到服务器
String firstStr="\""+ClientName+"\":"+"登入成功";
DataOutputStream firstdataOutputStream = new DataOutputStream(s.getOutputStream());
//发送用户名到服务端
firstdataOutputStream.writeUTF(firstStr);
firstdataOutputStream.flush();
//
this.setBounds(300,300,300,400);
//this.setSize(500, 300); //设置窗体大小
setLocationRelativeTo(null); //设置窗口居中
this.setVisible(true); //窗体设置为可见
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtf.requestFocus();
//
jtf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
String str=jtf.getText();
try {
if(str.length()>0) {
str="\""+ClientName+"\":"+str;
sendMessage(str, s);
jtf.setText("");
}
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
str="\""+ClientName+"\":"+"已退出";
sendMessage(str,s);
}
}
});
}
//客服端发送信息到服务器
protected void sendMessage(String message, Socket s) {
try {
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(message);
dos.flush();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public static void main(String[] args) {
new Login();
}
}
//定义线程类,读取服务器发送的信息
class ThreadClient extends Thread {
private Socket s;
private Client clientChat;
ThreadClient(Socket socket, Client clientChat) {
this.s = socket;
this.clientChat = clientChat;
}
@Override
public void run() {
String message;
try {
while (true) {
DataInputStream DataInputStream = new DataInputStream(s.getInputStream());
message = DataInputStream.readUTF();
clientChat.jtf.setText("");
clientChat.jta.append(message+"\n");
}
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message="\""+clientChat.ClientName+"\":"+"已退出";
clientChat.sendMessage(message,s);
}
}
}
服务端
import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import javax.naming.ldap.LdapName;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Server extends JFrame {
//static List<Socket>ls=new ArrayList<Socket>();
//static List<String>lname=new ArrayList<String>();
public static Map<Socket,String> socketsMaps
= Collections.synchronizedMap(new HashMap<Socket,String>());
//
ServerSocket sc=null;
Socket s=null;
public JTextArea jta=new JTextArea(10,20);
public JScrollPane jsp=new JScrollPane(jta);
public String ServerName="服务器";
static int number=1;
Server() throws IOException{
super();
setTitle("服务器");
jta.setEditable(false); //文本显示框不可编辑
this.add(jsp,BorderLayout.CENTER);
//默认的设置是超过文本框才会显示滚动条,以下设置让滚动条一直显示
jsp.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//this.add(jta,BorderLayout.CENTER); //不需要重复添加
this.setBounds(300,300,300,400);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//
}
public void init() {
int count = 0; // 记录登录到该服务器的客户端个数
try {
sc = new ServerSocket(9995); // 创建一个ServerSocket对象,端口号为1906
jta.append("服务器已启动"+'\n');
while (true) {
Socket socket=sc.accept();
new ThreadServer(socket,this).start();
}
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException{
new Server().init();
}
}
class ThreadServer extends Thread {
private Socket ts;
private Server tsr;
ThreadServer(){};
ThreadServer(Socket s,Server sr)
{
this.ts = s;
this.tsr=sr;
}
public void run() {
try {
while(true)
{
DataInputStream dis = new DataInputStream(ts.getInputStream());
String message=dis.readUTF();
if(message.endsWith(":登入成功")) {
message.replaceAll(":登入成功", "");
tsr.socketsMaps.put(ts,message);
}
tsr.jta.append(message+'\n');
Set<Socket> sockets = tsr.socketsMaps.keySet();
for(Socket tts : sockets) {
DataOutputStream dos = new DataOutputStream(tts.getOutputStream());
dos.writeUTF(message);
dos.flush();
}
}
}
catch (IOException e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
}
来源:https://blog.csdn.net/hrd535523596/article/details/111634368


猜你喜欢
- 延伸:以后除了可以为实体类注入属性,还可以为配置类注入相关的配置信息1.编写实体类@Component@ConfigurationPrope
- 跟同事讨论到- 用C# Stopwatch 取得效能数值,Stopwatch.ElapsedMilliseconds 只到毫秒(ms),如果
- 本文实例讲述了Java接口的简单定义与实现方法。分享给大家供大家参考,具体如下:1、接口是Java中最终要的概念,接口可以理解为一种特殊的类
- 本文实例讲述了Android开发实现ImageView加载摄像头拍摄的大图功能。分享给大家供大家参考,具体如下:这个方法是从官方demo中摘
- 先来看看效果图先分析饼状图的构成,非常明显,饼状图就是一个又一个的扇形构成的,每个扇形都有不同的颜色,对应的有名字,数据和百分比。经以上信息
- 一般java在执行CMD命令时,通常是使用Runtime.getRuntime.exec(command)来执行的,这个方法有两种细节要注意
- 前言 dubbo是一款非常优秀的服务治理型RPC框架,dubbo的优秀在于,庞大的架构体
- 前言RadioGroup是继承LinearLayout,只支持横向或者竖向两种布局。所以在某些情况,比如多行多列布局,RadioGroup就
- 1.图集导航1.1 为什么对包名的命名要有所规范呢!使用规范的命名有益于程序的开发和后期阅读通俗的说:就是自己写的代码别人也能看的懂,代码结
- 前言Android的编辑框控件EditText在平常编程时会经常用到,有时候会对编辑框增加某些限制,如限制只能输入数字,最大输入的文字个数,
- 介绍非常简单的一个计时器,没有太多原理,我们直接上代码。先看课程目标课程目标就是一个简单的计时器,我们直接上使用示例吧界面里有一个计时器,4
- Activity是Android组件中最基本也是最为常见用的四大组件之一,在 android开发中 ,运用极为广泛,作为初学者需要熟练掌握,
- JavaWeb项目部署到服务器详细步骤本地准备在eclipse中将项目打成war文件:鼠标右键要部署到服务器上的项目导出项目数据库文件MyS
- 现象: 1. 表面现象: 方法中输出的日志, 日志文件中找不到, 也没有任何报错(即@Async标注的方法没有执行, 也没有报错)2. 分析
- 这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件。一、简介Add sleuth to
- 第一步:项目中资源配置文件夹(resources文件夹)下先新增测试环境application-dev.yml和application-pr
- 最近想关闭一个包的日志打印,经过一番研究实际上就一句话的事,一直没成功是因为name写错了。<logger name="pa
- SqlMapConfig.xml的约束,也就是Mybatis主配置文件的约束<?xml version="1.0"
- 本文实例为大家解析了Zxing生成二维码的经典案例,供大家参考,具体内容如下1、首先呢,先编译 compile ‘com.google.zx
- 本文主要介绍Java中的rmi的基本使用1:项目架构api:主要是接口的定义,url地址,端口号rmiconsumer:rmi服务的调用者r