亲宝软件园·资讯

展开

javaGUI多人聊天功能

段茜琳 人气:0

服务器

package com.ff.chat.chatserver.frame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;

public class ServerFrame extends JFrame {
    JTextArea msgArea;
    ArrayList<Socket> socketArrayList = new ArrayList<>();
    boolean serverFlag = true;//服务器启动标志
    StringBuffer sb = new StringBuffer();
    ServerSocket serverSocket;
    //创建服务器端的显示窗口
    public void creatFrame(){
        this.setTitle("聊天室-服务器端");
        this.setSize(500,500);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

        //创建一个面板
        JPanel jp = new JPanel(new BorderLayout());

        //中间面板
        JPanel centerPanel = new JPanel();
        msgArea = new JTextArea(30,40);
        msgArea.setEditable(false);
        JScrollPane jsp = new JScrollPane(msgArea);
        centerPanel.add(jsp);

        jp.add(centerPanel);

        this.add(jp);
        this.setVisible(true);
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                int res = JOptionPane.showConfirmDialog(null,"确定要关闭服务器吗?",
                        "操作提示",JOptionPane.OK_CANCEL_OPTION);
                if(res == 0){
                    try {
                        dispose();
                        serverSocket.close();
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
            }
        });
    }

    //启动服务器,创建ServerSocket
    public void startServer(){
        try {
            //创建ServerSocket
            serverSocket = new ServerSocket(9998);
            System.out.println("等待客户端连接");

            //循环监听客户端连接
            while (serverFlag){
                if(serverSocket.isClosed()){
                    serverFlag = false;
                    break;
                }
                Socket socket = serverSocket.accept();

                System.out.println("客户端连接成功");
                socketArrayList.add(socket);

                //为每一个客户端开启一个线程,监听客户端发来的消息
                new ServerThread(socket).start();
            }

        } catch (BindException b) {
            b.printStackTrace();
            System.out.println("服务器端口被占用");
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器启动失败");
            serverFlag = false;
        }
    }

    //创建一个内部类,开启一个线程,接收消息
    class ServerThread extends Thread{
        Socket socket;
        DataInputStream in;
        DataOutputStream out;
        boolean clientFlag = true;

        public ServerThread(Socket socket){
            this.socket = socket;
            try {
                this.in = new DataInputStream(socket.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            //监听接收客户端发送的消息
            while (clientFlag){
                if(socket.isClosed()){
                    break;
                }
                try {
                    String msg = in.readUTF();//读到客户端发送的消息
                    sb.append(msg+"\n");
                    System.out.println(sb);
                    msgArea.setText(sb.toString());

                    //从服务器端向客户端发送消息
                    if(socketArrayList.size() > 0){
                        Iterator<Socket> it = socketArrayList.iterator();
                        while (it.hasNext()){
                            Socket soc = it.next();
                            if(soc.isClosed()){//当客户端某个socket已经为关闭状态,移除此socket
                                it.remove();
                                continue;
                            }
                            //客户端socket如果没有关闭,向客户端发送消息
                            out = new DataOutputStream(soc.getOutputStream());
                            out.writeUTF(sb.toString());
                            out.flush();
                        }
                    }
                } catch (EOFException ef){
                    System.out.println("ip为:"+socket.getInetAddress()+"的客户端下线了");
                    clientFlag = false;
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
package com.ff.chat.chatserver.frame;

public class ServerRun {

    public static void main(String[] args) {
        ServerFrame serverFrame = new ServerFrame();
        serverFrame.creatFrame();
        serverFrame.startServer();

    }
}

客户端

注意:要在自己的电脑上运行多次客户端需要勾选如下选项

1.登录界面

package com.ff.chat.chatclient.frame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;

public class LoginFrame extends JFrame {

    JTextField accountField = null;

    //创建窗口
    public void creatFrame(){
        this.setTitle("聊天窗口");
        this.setSize(400,400);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);

        /*
        * 创建一个4行1列的面板
        * */
        JPanel jp = new JPanel(new GridLayout(4,1));

        //欢迎登陆面板
        JPanel welcomePanel = new JPanel();
        JLabel welcomLabel = new JLabel("欢迎登陆");
        welcomePanel.add(welcomLabel);

        //账号面板
        JPanel accountPanel = new JPanel();
        JLabel accountLabel = new JLabel("账号");
        accountField = new JTextField(15);
        accountPanel.add(accountLabel);
        accountPanel.add(accountField);

        //密码面板
        JPanel passwordPanel = new JPanel();
        JLabel passwordLabel = new JLabel("密码");
        JPasswordField passwordField = new JPasswordField(15);
        passwordPanel.add(passwordLabel);
        passwordPanel.add(passwordField);

        //登录按钮面板
        JPanel btnPanel = new JPanel();
        JButton loginBtn = new JButton("登录");
        JButton regBtn = new JButton("注册");
        btnPanel.add(loginBtn);
        btnPanel.add(regBtn);

        jp.add(welcomePanel);
        jp.add(accountPanel);
        jp.add(passwordPanel);
        jp.add(btnPanel);
        this.add(jp);

        this.setVisible(true);

        //组件绑定事件监听
        loginBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获得账号密码
                String account = accountField.getText();
                String password = new String(passwordField.getPassword());
                if(account.length() == 0){
                    JOptionPane.showMessageDialog(null,"账号不能为空",
                            "操作提示",JOptionPane.WARNING_MESSAGE);
                    return;
                }
                if(password.length() == 0){
                    JOptionPane.showMessageDialog(null,"密码不能为空",
                            "操作提示",JOptionPane.WARNING_MESSAGE);
                    return;
                }

                //预留2.0版本 与数据库交互

                //连接服务器,创建Socket对象
                try {
                    Socket socket = new Socket("192.168.31.179",9998);//该地址为要连接的服务器的地址
                    new ClientFrame(socket,account).creatFrame();
                    dispose(); //释放当前登录窗口
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                    JOptionPane.showMessageDialog(null,"服务器连接失败",
                            "操作提示",JOptionPane.WARNING_MESSAGE);
                }
            }
        });
    }


}

2.聊天界面

package com.ff.chat.chatclient.frame;

import com.ff.chat.chatclient.utils.DateUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;

public class ClientFrame extends JFrame {

    String account;
    Socket socket;
    DataOutputStream out;//数据输出字节流
    DataInputStream in;//数据输入字节流
    JTextArea msgArea;


    //创建聊天窗口时,初始化数据
    public ClientFrame(Socket socket,String account){
        this.socket = socket;
        this.account = account;
        try {
            out = new DataOutputStream(socket.getOutputStream());
            in = new DataInputStream(socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //创建聊天窗口
    public void creatFrame(){
        this.setTitle("聊天窗口-"+account);
        this.setSize(500,500);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

        //创建一个面板
        JPanel jp = new JPanel(new BorderLayout());

        //中间面板
        JPanel centerPanel = new JPanel();
        msgArea = new JTextArea(30,40);
        msgArea.setEditable(false);//不可以直接编辑
        JScrollPane jsp = new JScrollPane(msgArea);
        centerPanel.add(jsp);

        //底部面板
        JPanel bottomPanel = new JPanel();
        JTextField msg = new JTextField(30);
        JButton sendBtn = new JButton("发送");
        bottomPanel.add(msg);
        bottomPanel.add(sendBtn);

        jp.add(centerPanel);
        jp.add(bottomPanel,BorderLayout.SOUTH);

        this.add(jp);
        this.setVisible(true);

        //发送按钮添加监听事件
        sendBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String m = msg.getText(); //获得客户端输入的聊天内容
                if(m.length() == 0){
                    JOptionPane.showMessageDialog(null,"不能发送空白消息");
                    return;
                }
                //向服务器发送消息
                try {
                    String ms = account+":"+DateUtil.dateStr(new Date())+"\n"+m;
                    out.writeUTF(ms);//向服务器发送消息
                    out.flush();
                    msg.setText("");//发送成功,清空聊天文本框
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                    JOptionPane.showMessageDialog(null,"服务器连接失败");
                }

            }
        });

        //聊天窗口添加事件监听
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                int res = JOptionPane.showConfirmDialog(null,"你确定要退出吗?",
                        "操作提示",JOptionPane.OK_CANCEL_OPTION);
                if(res == 0){
                    dispose();
                    new LoginFrame().creatFrame();
                }
                try {
                    socket.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        });

        //启动一个线程,监听服务器是否向客户端发送了消息
        new ClientThread(socket).start();
    }

    //创建一个内部类
    class ClientThread extends Thread{
        //接收从服务器发来的消息
        Socket socket;
        boolean serverFlag = true;

        public ClientThread(Socket socket){
            this.socket = socket;
        }

        @Override
        public void run(){
            //监听接收服务器发来的消息
            while (serverFlag){
                try {
                    String ms = in.readUTF();
                    msgArea.setText(ms);
                } catch (IOException e) {
                    System.out.println("客户端"+account+"下线了");
                    serverFlag = false;
                }
            }
        }
    }
}

3.运行客户端

package com.ff.chat.chatclient.frame;

public class ClientRun {

    public static void main(String[] args) {
        new LoginFrame().creatFrame();
    }
}

加载全部内容

相关教程
猜你喜欢
用户评论