JAVA多人聊天室(UDP)

介绍

实现图形界面的多人聊天程序(UDP)

➢采用图形界面进行交互

➢通过组播维护聊天室成员(加入或退出)

➢支持发送消息给聊天室内所有成员

➢支持发送消息给聊天室内指定成员

实现效果

登陆界面

如果不输入用户名,用户名自动设置为未知

三个窗口分别来自三个成员,加入顺序为:aa、cc、bb,三个用户之间可以互相发送私信,也可以在聊天室群聊。

完整代码

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.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.HashSet;
import java.util.Set;

public class UDPChat {
    private static final int PORT = 12345;
    private static final String MULTICAST_ADDRESS = "230.0.0.1"; // Multicast address for group communication
    private static Set<String> users = new HashSet<>();
    private static DefaultListModel<String> userListModel = new DefaultListModel<>();

    public static void main(String[] args) {
        // Prompt for username
        String username = JOptionPane.showInputDialog(null, "Enter your username:", "Username", JOptionPane.PLAIN_MESSAGE);
        if (username == null || username.trim().isEmpty()) {
            username = "未知";
        }
        // 创建主框架
        JFrame frame = new JFrame("ChatBox - " + username);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 400);
        // 设置布局
        frame.setLayout(new BorderLayout());
        JTextArea messageDisplayArea = new JTextArea();
        messageDisplayArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(messageDisplayArea);
        JPanel userInfoPanel = new JPanel();
        userInfoPanel.setLayout(new BorderLayout());
        JLabel userInfoLabel = new JLabel("用户:");
        JList<String> userList = new JList<>(userListModel);
        userInfoPanel.add(userInfoLabel, BorderLayout.NORTH);
        userInfoPanel.add(new JScrollPane(userList), BorderLayout.CENTER);
        JPanel messageSendPanel = new JPanel();
        messageSendPanel.setLayout(new BorderLayout());
        JTextField messageTextField = new JTextField();
        JButton sendButton = new JButton("Send");
        JButton sendPrivateButton = new JButton("私信");
        messageSendPanel.add(messageTextField, BorderLayout.CENTER);
        messageSendPanel.add(sendButton, BorderLayout.EAST);
        messageSendPanel.add(sendPrivateButton, BorderLayout.WEST);
        // 添加组件到框架
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(userInfoPanel, BorderLayout.EAST);
        frame.add(messageSendPanel, BorderLayout.SOUTH);
        // 创建UDP处理器
        UDPHandler udpHandler = new UDPHandler(messageDisplayArea, username);
        new Thread(udpHandler).start();
        // 发送按钮的监听器
        String finalUsername = username;
        sendButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String message = messageTextField.getText();
                if (!message.isEmpty()) {
                    messageDisplayArea.append(finalUsername + ": " + message + "\n");
                    udpHandler.sendMessage(message);
                    messageTextField.setText("");
                }
            }
        });

        // 发送私信按钮的监听器
        sendPrivateButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String message = messageTextField.getText();
                String recipient = userList.getSelectedValue();
                if (recipient != null && !message.isEmpty()) {
                    messageDisplayArea.append("发送私信至 " + recipient + ": " + message + "\n");
                    udpHandler.sendPrivateMessage(message, recipient);
                    messageTextField.setText("");
                }
            }
        });

        // 添加窗口监听器以处理窗口关闭事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                udpHandler.sendLeaveMessage();
                super.windowClosing(e);
            }
        });

        // 设置主框架可见
        frame.setVisible(true);
        // Notify others of new user
        udpHandler.sendJoinMessage();
    }

    public static void updateUserList(String username) {
        if (users.add(username)) {
            SwingUtilities.invokeLater(() -> {
                userListModel.addElement(username);
            });
        }
    }

    public static void removeUser(String username) {
        if (users.remove(username)) {
            SwingUtilities.invokeLater(() -> {
                userListModel.removeElement(username);
            });
        }
    }

    public static void broadcastUserList(MulticastSocket socket) {
        try {
            InetAddress group = InetAddress.getByName(MULTICAST_ADDRESS);
            StringBuilder userListMessage = new StringBuilder("USERLIST:");
            for (String user : users) {
                userListMessage.append(user).append(",");
            }
            byte[] buffer = userListMessage.toString().getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, PORT);
            socket.send(packet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class UDPHandler implements Runnable {
    private static final int BUFFER_SIZE = 1024;
    private MulticastSocket socket;
    private DatagramSocket privateSocket;
    private JTextArea messageDisplayArea;
    private String username;
    private static final int PORT = 12345;
    private static final String MULTICAST_ADDRESS = "230.0.0.1";

    public UDPHandler(JTextArea messageDisplayArea, String username) {
        this.messageDisplayArea = messageDisplayArea;
        this.username = username;
        try {
            socket = new MulticastSocket(PORT);
            InetAddress group = InetAddress.getByName(MULTICAST_ADDRESS);
            socket.joinGroup(group);
            privateSocket = new DatagramSocket();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        byte[] buffer = new byte[BUFFER_SIZE];
        while (true) {
            try {
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);
                String receivedMessage = new String(packet.getData(), 0, packet.getLength());
                handleMessage(receivedMessage);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void handleMessage(String message) {
        if (message.startsWith("JOIN:")) {
            String newUser = message.substring(5);
            UDPChat.updateUserList(newUser);
            SwingUtilities.invokeLater(() -> messageDisplayArea.append(newUser + " 加入群聊.\n"));
            UDPChat.broadcastUserList(socket);
        } else if (message.startsWith("LEAVE:")) {
            String leavingUser = message.substring(6);
            UDPChat.removeUser(leavingUser);
            SwingUtilities.invokeLater(() -> messageDisplayArea.append(leavingUser + " 离开群聊.\n"));
            UDPChat.broadcastUserList(socket);
        } else if (message.startsWith("USERLIST:")) {
            String[] userArray = message.substring(9).split(",");
            for (String user : userArray) {
                if (!user.isEmpty()) {
                    UDPChat.updateUserList(user);
                }
            }
        } else if (message.startsWith("PRIVATE:")) {
            String[] parts = message.split(":", 4);
            String toUser = parts[1];
            String fromUser = parts[2];
            String privateMessage = parts[3];
            if (toUser.equals(username)) {
                SwingUtilities.invokeLater(() -> messageDisplayArea.append("私信来自" + fromUser + ": " + privateMessage + "\n"));
            }
        } else {
            SwingUtilities.invokeLater(() -> {
                if (!message.startsWith(username + ":")) {
                    messageDisplayArea.append(message + "\n");
                }
            });
        }
    }

    public void sendMessage(String message) {
        try {
            InetAddress group = InetAddress.getByName(MULTICAST_ADDRESS);
            String fullMessage = username + ": " + message;
            byte[] buffer = fullMessage.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, PORT);
            socket.send(packet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendPrivateMessage(String message, String recipient) {
        try {
            InetAddress group = InetAddress.getByName(MULTICAST_ADDRESS);
            String fullMessage = "PRIVATE:" + recipient + ":" + username + ":" + message;
            byte[] buffer = fullMessage.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, PORT);
            privateSocket.send(packet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendJoinMessage() {
        try {
            InetAddress group = InetAddress.getByName(MULTICAST_ADDRESS);
            String joinMessage = "JOIN:" + username;
            byte[] buffer = joinMessage.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, PORT);
            socket.send(packet);
            UDPChat.updateUserList(username);
            UDPChat.broadcastUserList(socket);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendLeaveMessage() {
        try {
            InetAddress group = InetAddress.getByName(MULTICAST_ADDRESS);
            String leaveMessage = "LEAVE:" + username;
            byte[] buffer = leaveMessage.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, PORT);
            socket.send(packet);
            UDPChat.removeUser(username);
            UDPChat.broadcastUserList(socket);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值