java实现多人聊天室可视化

网友投稿 304 2022-07-24


编写一个 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 Listls=new ArrayList();

//static Listlname=new ArrayList();

public static Map socketsMaps

= Collections.synchronizedMap(new HashMap());

//

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 runIspis() {

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 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();

}

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解Spring中Bean后置处理器(BeanPostProcessor)的使用
下一篇:Java定义画板类的方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~