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(); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
赞 (0)