java实现多人聊天室可视化

2022-11-13 10:11:14 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();
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关文章