首页>代码>java swing通过socket模拟多人聊天>/chat/src/chatroom/ServerControl.java
package chatroom;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.border.*;
import java.util.*;

public class ServerControl extends JFrame {
    JPanel contentPane;
    JButton btnStart = new JButton();
    JLabel lblState = new JLabel();
    TitledBorder titledBorder1 = new TitledBorder("");
    JScrollPane srpList = new JScrollPane();

    DefaultListModel dlmUsers = new DefaultListModel();
    JList lstUsers = new JList(dlmUsers);
    JScrollPane srpChatMessage = new JScrollPane();
    DefaultListModel dlmChat = new DefaultListModel();
    JList lstChat = new JList(dlmChat);
    ServerSocket ss;
    public static int PORT = 8888;
    public boolean flag = true;
    JTextField txtMsg = new JTextField();
    JComboBox cmbType = new JComboBox();
    JButton btnSend = new JButton();
    JButton btnKick = new JButton();
    JButton btnSave = new JButton();
    JButton btnClear = new JButton();

    public ServerControl() {
        try {
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            jbInit();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * Component initialization.
     *
     * @throws java.lang.Exception
     */
    private void jbInit() throws Exception {
        lstChat.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        lstChat.setAutoscrolls(true);
        this.srpChatMessage.setAutoscrolls(true);
        contentPane = (JPanel) getContentPane();
        contentPane.setLayout(null);
        setSize(new Dimension(395, 500));
        setResizable(false);
        setTitle("服务器端");
        btnStart.setBounds(new Rectangle(19, 16, 103, 27));
        btnStart.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        btnStart.setText("启动服务器");
        btnStart.addActionListener(new ServerControl_btnStart_actionAdapter(this));
        lblState.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        lblState.setForeground(Color.red);
        Border border = BorderFactory.createEtchedBorder(Color.white,
                new Color(170, 170, 170));
        lblState.setBorder(new TitledBorder(border, "服务器状态",
                                            TitledBorder.ABOVE_TOP,
                                            TitledBorder.CENTER,
                                            new Font("Dialog", Font.PLAIN, 12)));
        lblState.setHorizontalAlignment(SwingConstants.CENTER);
        lblState.setText("关闭");
        lblState.setBounds(new Rectangle(142, 8, 230, 34));
        srpList.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        srpList.setBorder(new TitledBorder(border, "用户列表",
                                           TitledBorder.ABOVE_TOP,
                                           TitledBorder.CENTER,
                                           new Font("Dialog", Font.PLAIN, 12)));
        srpList.setBounds(new Rectangle(23, 62, 96, 287));
        srpChatMessage.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        srpChatMessage.setBorder(new TitledBorder(border, "聊天记录",
                                                  TitledBorder.ABOVE_TOP,
                                                  TitledBorder.CENTER,
                                                  new Font("Dialog", Font.PLAIN,
                12)));
        srpChatMessage.setBounds(new Rectangle(140, 62, 235, 284));
        txtMsg.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        txtMsg.setText("");
        txtMsg.setBounds(new Rectangle(27, 390, 218, 27));
        cmbType.addItem("群聊");
        cmbType.addItem("私聊");
        cmbType.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        cmbType.setBounds(new Rectangle(264, 390, 106, 27));
        cmbType.setBorder(new LineBorder(Color.GRAY));
        btnSend.setBounds(new Rectangle(263, 426, 110, 21));
        btnSend.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        btnSend.setText("发送消息");
        btnSend.addActionListener(new ServerControl_btnSend_actionAdapter(this));
        btnKick.setBounds(new Rectangle(28, 357, 78, 21));
        btnKick.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        btnKick.setText("踢人");
        btnKick.addActionListener(new ServerControl_btnKick_actionAdapter(this));
        btnSave.setBounds(new Rectangle(118, 357, 119, 21));
        btnSave.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        btnSave.setText("保存聊天记录");
        btnSave.addActionListener(new ServerControl_btnSave_actionAdapter(this));
        btnClear.setBounds(new Rectangle(251, 357, 119, 21));
        btnClear.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        btnClear.setText("清除聊天信息");
        btnClear.addActionListener(new ServerControl_btnClear_actionAdapter(this));
        lstUsers.setFont(new java.awt.Font("Dialog", Font.PLAIN, 12));
        contentPane.add(btnStart);
        contentPane.add(srpList);
        contentPane.add(srpChatMessage);
        contentPane.add(lblState);
        contentPane.add(btnKick);
        contentPane.add(btnSave);
        contentPane.add(btnClear);
        contentPane.add(cmbType);
        contentPane.add(txtMsg);
        contentPane.add(btnSend);
        srpChatMessage.getViewport().add(lstChat);
        srpList.getViewport().add(lstUsers);
        lstUsers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    }

    //启动按钮
    public void btnStart_actionPerformed(ActionEvent e) {
        String text = btnStart.getText();
        if (text.equals("启动服务器")) {
            startServer();
        } else {
            stopServer();
        }
    }

    //启动服务器
    public void startServer() {
        try {
            flag=true;
            ss = new ServerSocket(PORT);
            lblState.setText("服务器已经启动,在侦听" + PORT + "端口");
            btnStart.setText("关闭服务器");
            new ListenerThread().start();
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "服务器启动失败!");
        }
    }

    //关闭服务器
    public void stopServer() {
        flag = false;
        lblState.setText("服务器已经关闭");
        btnStart.setText("启动服务器");
        try {
            DefaultListModel dlm=(DefaultListModel)lstUsers.getModel();
            Enumeration emu=dlm.elements();
            while(emu.hasMoreElements())
            {
                ((ClientBean)emu.nextElement()).getS().close();
            }
            dlm.clear();
            ss.close();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "关闭服务器产生错误!");
        }
    }

    //踢人功能
    public void btnKick_actionPerformed(ActionEvent e) {
        Object obj = lstUsers.getSelectedValue();
        if (obj != null) {
            ClientBean cb = (ClientBean) obj;
            ((DefaultListModel) lstUsers.getModel()).removeElement(cb);
            try {
                cb.getS().close();
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                String msg = "管理员将【" + cb.getClientName() + "】赶出了聊天室";
                sendAll(msg);
                sendList();
            }
        } else {
            JOptionPane.showMessageDialog(null, "请从用户列表中选择您要踢出的人!");
        }
    }

    //保存聊天日志
    public void btnSave_actionPerformed(ActionEvent e) {
        JFileChooser jfc = new JFileChooser();
        jfc.setAcceptAllFileFilterUsed(false);
        jfc.setFileFilter(new MyFileFilter());
        int choice = jfc.showSaveDialog(this);
        if (choice == jfc.APPROVE_OPTION) {
            File destnation = jfc.getSelectedFile();
            try {
                BufferedWriter bw = new BufferedWriter(new FileWriter(
                        destnation.getAbsolutePath() + ".log", true));
                DefaultListModel dlm = (DefaultListModel) lstChat.getModel();
                Enumeration em = dlm.elements();
                while (em.hasMoreElements()) {
                    bw.write(em.nextElement().toString());
                    bw.newLine();
                }
                bw.close();
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "保存文件发生错误!");
            }
        }
    }

    //设置文件过滤器
    class MyFileFilter extends javax.swing.filechooser.FileFilter {
        public boolean accept(File f) {
            if (f.isDirectory() || f.getName().endsWith(".log")) {
                return true;
            } else {
                return false;
            }
        }

        public String getDescription() {
            return "日志文件(*.log)";
        }
    }


    //监听线程
    class ListenerThread extends Thread {
        public void run() {
            while (flag) {
                try {
                    Socket s = ss.accept();
                    //启动与客户端会话线程
                    new ChatThread(s).start();
                } catch (IOException ex) {
                    flag = false;
                }
            }
        }
    }

    //发送客户列表信息
    public void sendList()
    {
        DefaultListModel dlm=(DefaultListModel) lstUsers.getModel();
        Enumeration em =dlm.elements();
        while (em.hasMoreElements()) {
            ClientBean cb = (ClientBean) em.nextElement();
            cb.getOut().println("list:" + dlm.toString());
        }
    }

    //发送群聊信息
    public void sendAll(String msg) {
        ((DefaultListModel) lstChat.getModel()).addElement(msg);
        Enumeration em = ((DefaultListModel) lstUsers.getModel()).elements();
        while (em.hasMoreElements()) {
            ClientBean cb = (ClientBean) em.nextElement();
            cb.getOut().println(msg);
        }
    }

    //发送私聊信息
    public void sendPrivate(String text, ClientBean cb) {
        ((DefaultListModel) lstChat.getModel()).addElement(text);
        cb.getOut().println(text);
    }

    //清空聊天信息
    public void btnClear_actionPerformed(ActionEvent e) {
        int choice = JOptionPane.showConfirmDialog(null, "确认清空聊天记录吗?", "提示", JOptionPane.OK_CANCEL_OPTION);
        if (choice == JOptionPane.OK_OPTION) {
            ((DefaultListModel) lstChat.getModel()).clear();
        }
    }

    //发送消息
    public void btnSend_actionPerformed(ActionEvent e) {
        //获得输入的信息内容
        String text = txtMsg.getText().trim();
        txtMsg.setText("");
        if (text.equals("")) {
            JOptionPane.showMessageDialog(null, "消息不能为空!");
        } else {
            //获得发送的类型
            int index = cmbType.getSelectedIndex();
            //索引为0代表是群聊
            if (index == 0) {
                String msg = "管理员对所有人说:" + text;
                sendAll(msg);
            }
            //否则是私聊
            else {
                Object obj = lstUsers.getSelectedValue();
                if (obj == null) {
                    JOptionPane.showMessageDialog(null, "私聊必须要选择一个客户");
                } else {
                    ClientBean cb = (ClientBean) obj;
                    String msg = "管理员对" + cb.getClientName() + "说:" + text;
                    sendPrivate(msg, cb);
                }
            }
        }
    }

    public boolean existsClientName(String clientName)
    {
        boolean flag=false;
        java.util.Enumeration emu=((DefaultListModel) lstUsers.getModel()).elements();
        while(emu.hasMoreElements())
        {
            ClientBean cb=(ClientBean)emu.nextElement();
            if(cb.getClientName().equals(clientName))
            {
                flag=true;
                break;
            }
        }
        return flag;
    }
    //客户端会话线程
    class ChatThread extends Thread {
        private Socket s;
        public ChatThread(Socket s) {
            this.s = s;
        }

        public void run() {
            try {
                PrintWriter out = new PrintWriter(s.getOutputStream(), true);
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                //获得客户端昵称
                String clientName = br.readLine();
                if(existsClientName(clientName)){
                    s.close();
                }
                else{
                    //创建客户端BEAN
                    ClientBean cb = new ClientBean(clientName, out, s);
                    //获得用户列表
                    DefaultListModel dlm = (DefaultListModel) lstUsers.getModel();

                    //将客户端添加到ServerControl界面
                    dlm.addElement(cb);
                    //欢迎词
                    String welcome = "☆☆★★★欢迎" + clientName + "来到JAVA聊天室★★★☆☆";
                    //向各客户端发送欢迎词
                    sendAll(welcome);
                    sendList();
                    //启动获取该客户端信息线程
                    new GetThread(br, cb).start();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }


    //获取客户端信息线程
    class GetThread extends Thread {
        private BufferedReader br;
        private ClientBean cb;
        private DefaultListModel dlm = (DefaultListModel) lstChat.getModel();

        public GetThread(BufferedReader br, ClientBean cb) {
            this.br = br;
            this.cb = cb;
        }

        public void run() {
            try {
                while (true) {
                    String text = br.readLine();
                    String[] content = text.split(":");
                    if (content[1].equals("all")) {
                        String msg = content[0] + "对所有人说:" + content[2];
                        sendAll(msg);
                    } else {
                        int index = Integer.parseInt(content[1]);
                        Object obj=lstUsers.getModel().getElementAt(index);
                        if(obj!=null)
                        {
                            ClientBean cb=(ClientBean)obj;
                            String msg=content[0]+"对"+cb.getClientName()+"说:"+content[2];
                            sendPrivate(msg,cb);
                        }
                    }
                }
            }
            //当客户端直接关闭窗体时,从JLIST直接移除该客户端信息
            catch (SocketException se) {
                if(flag)
                {
                    DefaultListModel dlm = (DefaultListModel) lstUsers.getModel();
                    //判断该客户端是否是被管理员踢出去的,如果不是就欢送
                    if (dlm.contains(cb)) {
                        dlm.removeElement(cb);
                        String goodbye = "<html>欢送" + cb.getClientName() +
                                         "离开聊天室</html>";
                        sendAll(goodbye);
                        sendList();
                    }
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

}


class ServerControl_btnSend_actionAdapter implements ActionListener {
    private ServerControl adaptee;
    ServerControl_btnSend_actionAdapter(ServerControl adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnSend_actionPerformed(e);
    }
}


class ServerControl_btnClear_actionAdapter implements ActionListener {
    private ServerControl adaptee;
    ServerControl_btnClear_actionAdapter(ServerControl adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnClear_actionPerformed(e);
    }
}


class ServerControl_btnSave_actionAdapter implements ActionListener {
    private ServerControl adaptee;
    ServerControl_btnSave_actionAdapter(ServerControl adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnSave_actionPerformed(e);
    }
}


class ServerControl_btnKick_actionAdapter implements ActionListener {
    private ServerControl adaptee;
    ServerControl_btnKick_actionAdapter(ServerControl adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnKick_actionPerformed(e);
    }
}


class ServerControl_btnStart_actionAdapter implements ActionListener {
    private ServerControl adaptee;
    ServerControl_btnStart_actionAdapter(ServerControl adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.btnStart_actionPerformed(e);
    }
}
最近下载更多
1690356080  LV37 4月23日
CL200228  LV4 2023年5月4日
oyonogul  LV1 2022年11月21日
youwuzuichen  LV10 2022年9月8日
huevnn  LV5 2022年6月16日
bearloadprogress  LV7 2022年5月12日
liys1234  LV9 2022年4月22日
装了磁铁的果冻  LV1 2022年1月7日
9843637  LV9 2021年12月14日
tttyyyytt  LV2 2021年6月22日
最近浏览更多
qwertasdfgkwuejwjwjw  LV1 6月27日
周鸣郝  LV2 5月26日
1690356080  LV37 4月23日
krispeng  LV9 4月15日
lalalla159  LV3 2023年12月2日
Sutnuf 2023年11月27日
暂无贡献等级
13161895  LV1 2023年7月4日
2017143155  LV12 2023年6月24日
链路预测 2023年6月19日
暂无贡献等级
17683946472  LV9 2023年6月8日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友