BIO GUI实现聊天室

服务端:

  1. 转发消息
  2. 群聊功能
  3. 私聊功能

服务端:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class Server {

    // 记录在线客户端
    public static Map<Socket,String> onlineSockets = new HashMap<>();
    // 方便私发消息,找到客户端
    public static Map<String, Socket> nameSockets = new HashMap<>();

    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(8888);
            while (true) {
                Socket socket = ss.accept();
                new ServerThread(socket).start();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

服务端处理消息

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Map;

public class ServerThread extends Thread {
    private Socket socket;

    private String name;

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

    @Override
    public void run() {
        try (DataInputStream dis = new DataInputStream(socket.getInputStream())){
            while (true) {
                // 1 登录
                // 2 / 3 发送信息
                // 4 下线
                int clientStatus = dis.readInt();

                if (clientStatus == 1) {
                    String name = dis.readUTF();
                    System.out.println("用户:"+name);
                    this.name = name;
                    Server.onlineSockets.put(socket, name);
                    Server.nameSockets.put(name,socket);
                }
                send(clientStatus, dis);
            }
        } catch (Exception e) {
            System.out.println(e);
            System.out.println("有人下线了");
            Server.onlineSockets.remove(socket);
            Server.nameSockets.remove(name);
            send(4, null);
        }
    }

    public void send(int flag, DataInputStream dis) {
        Map<Socket, String> onlineSockets = Server.onlineSockets;
        if (flag == 2) {
            try {
                String m = dis.readUTF();

                for (Map.Entry<Socket, String> client : onlineSockets.entrySet()) {
                    Socket socketClient = client.getKey();
                    if (!socket.equals(socketClient)) {
                        DataOutputStream dos = new DataOutputStream(socketClient.getOutputStream());
                        String msg = this.name + "&&&" + m;
                        // 要先发此flag, 否则客户端无法处理
                        dos.writeInt(flag);
                        dos.writeUTF(msg);
                        dos.flush();
                    }
                }
            }catch (Exception e) {
                System.out.println(e);
            }
        } else if (flag == 3) {
            try {
                String m = dis.readUTF();
                String[] split = m.split(" ");
                String clientName = split[0].replace("@", "");
                Socket socket = Server.nameSockets.get(clientName);
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                String msg = this.name + "&&&" + split[1];
                System.out.println(msg);
                // 要先发此flag, 否则客户端无法处理
                dos.writeInt(flag);
                dos.writeUTF(msg);
                dos.flush();
            }catch (Exception e) {
                System.out.println("eeeeeeeeeeeeeee");
                System.out.println(e);
            }
        } else {

        }
    }
}

客户端

  1. 使用GUI搭建一个注册socket服务器
  2. 构建聊天室
  3. 处理客户端不同的消息
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Client extends JFrame {

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static Socket socket;

    public static void main(String[] args) {
        login();
    }

    public static void login() {
        int width = 400;
        int height = 876;
        int textFieldWidth = 120;
        int textFieldHeight = 24;

        JFrame frame = new JFrame();
        frame.setBounds(Window.WIDTH / 2 - width, 40, width, height);
        frame.setTitle("登录页面");
        frame.setLayout(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

        JTextField ip = new JTextField();
        ip.setLocation(160, 80);
        ip.setText("127.0.0.1");
        ip.setSize(textFieldWidth, textFieldHeight);
        frame.add(ip);

        JLabel ipLabel = new JLabel("Socket IP:");
        ipLabel.setLocation(40, 80);
        ipLabel.setSize(120, 24);
        frame.add(ipLabel);

        JTextField name = new JTextField();
        name.setLocation(160, 110);
        name.setSize(textFieldWidth, textFieldHeight);
        frame.add(name);

        JLabel nameLabel = new JLabel("昵称:");
        nameLabel.setLocation(40, 110);
        nameLabel.setSize(120, 24);
        frame.add(nameLabel);

        JButton jbtn = new JButton("登录");
        jbtn.setLocation(110, 140);
        jbtn.setSize(100, 30);
        frame.add(jbtn);
        frame.setVisible(true);
        jbtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    socket = new Socket(ip.getText(), 8888);
                    DataOutputStream dis = new DataOutputStream(socket.getOutputStream());
                    dis.writeInt(1);
                    dis.writeUTF(name.getText());
                    frame.setVisible(false);
                    chat(name.getText());
                    System.out.println("用户登录了");
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            }
        });
    }

    public static void chat(String name) {
        int width = 400;
        int height = 876;

        JFrame mainFrame = new JFrame();

        mainFrame.setBounds(Window.WIDTH / 2 - width, 40, width, height);
        mainFrame.setTitle("聊天界面: " + name);
        mainFrame.setLayout(null);

        Container con = mainFrame.getContentPane();

        JTextArea showArea = new JTextArea();
        showArea.setEditable(false);
        showArea.setLineWrap(true);

        JScrollPane jPanel = new JScrollPane(showArea);

        jPanel.setSize(width, height - 200);

        JTextArea inputArea = new JTextArea();
        inputArea.setRows(9);
        inputArea.setColumns(27);

        JButton jButton = new JButton("发送");
        jButton.setSize(120, 80);
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String text = inputArea.getText();
                if (text.length() > 0) {
                    boolean contains = text.contains("@");
                    inputArea.setText("");
                    try {
                        OutputStream os = socket.getOutputStream();
                        DataOutputStream dos = new DataOutputStream(os);
                        // @ 是私聊, 不加是群聊
                        dos.writeInt(contains ? 3 : 2);
                        dos.writeUTF(text);
                        dos.flush();
                        Date sendDate = new Date();
                        showArea.append("我:" + simpleDateFormat.format(sendDate) + "\n");
                        showArea.append(text + "\n");
                    } catch (Exception exception) {
                        System.out.println("发送消息异常");
                        System.out.println(exception);
                    }
                }
            }
        });

        JPanel op = new JPanel();
        op.setBackground(Color.pink);
        op.setLocation(0, 676);
        op.setSize(width, 200);

        // 加入到对应的容器中
        op.add(inputArea);
        op.add(jButton);

        con.add(jPanel, BorderLayout.CENTER);
        con.add(op, BorderLayout.SOUTH);
        mainFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        // 最后渲染
        mainFrame.setVisible(true);

        new Thread(new Runnable() {
            @Override
            public void run() {
                // 获取返回的消息
                try {
                    DataInputStream dis = new DataInputStream(socket.getInputStream());
                    while (true) {
                        int status = dis.readInt();
                        String msg = dis.readUTF();
                        if (status == 1) {
                            // 可以记录在线人是谁
                            String onLineUserName = msg;
                            System.out.println(onLineUserName);
                        } else if (status == 2) { // 接收别人发送的消息
                            String msgText = msg;
                            String[] split = msgText.split("&&&");
                            Date sendDate = new Date();
                            showArea.append(split[0] + " :" + simpleDateFormat.format(sendDate) + "\n");
                            showArea.append(split[1] + "\n");
                        } else if (status == 3) { // 接收别人发送的消息
                            String msgText = msg;
                            String[] split = msgText.split("&&&");
                            Date sendDate = new Date();
                            showArea.append(split[0] + " :" + simpleDateFormat.format(sendDate)  + " 向你私法了消息" + "\n");
                            showArea.append(split[1] + "\n");
                        }
                    }
                } catch (Exception e) {
                    System.out.println("异常信息");
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

GUI使用时,注意组件的加载顺序,将组件最后加入到要显示的地方。

启动server 和 客户端


image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容