局域网聊天

server:

import java.io.*;
import java.net.*;
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import org.json.JSONObject;

public class ChatServer {
    private static final int PORT = 12345;
    private static final String SECRET_KEY = "1234567890123456"; // 16 字节密钥
    private static Set<ClientHandler> clients = Collections.synchronizedSet(new HashSet<>());

    public static void main(String[] args) {
        System.out.println("服务器启动,等待客户端连接...");
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            while (true) {
                Socket clientSocket = serverSocket.accept();
                ClientHandler clientHandler = new ClientHandler(clientSocket);
                clients.add(clientHandler);
                new Thread(clientHandler).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class ClientHandler implements Runnable {
        private Socket socket;
        private String nickname;
        private BufferedReader in;
        private PrintWriter out;

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

        @Override
        public void run() {
            try {
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out = new PrintWriter(socket.getOutputStream(), true);

                // 接收并设置昵称
                String encryptedMessage = in.readLine();
                String decryptedMessage = decrypt(encryptedMessage);
                JSONObject json = new JSONObject(decryptedMessage);
                this.nickname = json.getString("nickname");

                broadcast("系统消息:" + nickname + " 加入了聊天室!");
                System.out.println("用户 " + nickname + " 已连接。");

                // 处理客户端消息
                String message;
                while ((encryptedMessage = in.readLine()) != null) {
                    decryptedMessage = decrypt(encryptedMessage);
                    json = new JSONObject(decryptedMessage);
                    message = json.getString("message");
                    broadcast(nickname + ":" + message);
                }
            } catch (Exception e) {
                System.out.println("用户 " + nickname + " 断开连接。");
            } finally {
                try {
                    clients.remove(this);
                    socket.close();
                    broadcast("系统消息:" + nickname + " 离开了聊天室。");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void broadcast(String message) {
            synchronized (clients) {
                for (ClientHandler client : clients) {
                    client.sendMessage(message);
                }
            }
        }

        private void sendMessage(String message) {
            try {
                JSONObject json = new JSONObject();
                json.put("message", message);
                String encryptedMessage = encrypt(json.toString());
                out.println(encryptedMessage);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private String encrypt(String data) throws Exception {
            Cipher cipher = Cipher.getInstance("AES");
            SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
        }

        private String decrypt(String data) throws Exception {
            Cipher cipher = Cipher.getInstance("AES");
            SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
            cipher.init(Cipher.DECRYPT_MODE, key);
            return new String(cipher.doFinal(Base64.getDecoder().decode(data)));
        }
    }
}

 

客户端代码(JSON 协议 + GUI + 加密

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.Base64;
import org.json.JSONObject;

public class ChatClient {
    private static final String SERVER_IP = "127.0.0.1";
    private static final int SERVER_PORT = 12345;
    private static final String SECRET_KEY = "1234567890123456"; // 16 字节密钥

    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private String nickname;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ChatClient::new);
    }

    public ChatClient() {
        initGUI();
    }

    private void initGUI() {
        JFrame frame = new JFrame("局域网聊天");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 500);

        JTextArea chatArea = new JTextArea();
        chatArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(chatArea);

        JTextField inputField = new JTextField();
        JButton sendButton = new JButton("发送");

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(inputField, BorderLayout.CENTER);
        panel.add(sendButton, BorderLayout.EAST);

        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(panel, BorderLayout.SOUTH);

        frame.setVisible(true);

        sendButton.addActionListener(e -> sendMessage(inputField, chatArea));
        inputField.addActionListener(e -> sendMessage(inputField, chatArea));

        String userNickname = JOptionPane.showInputDialog(frame, "请输入昵称:");
        if (userNickname == null || userNickname.trim().isEmpty()) {
            System.exit(0);
        }
        this.nickname = userNickname;

        try {
            connectToServer(chatArea);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(frame, "无法连接到服务器!", "错误", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
    }

    private void connectToServer(JTextArea chatArea) throws IOException {
        socket = new Socket(SERVER_IP, SERVER_PORT);
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new PrintWriter(socket.getOutputStream(), true);

        // 发送昵称
        JSONObject json = new JSONObject();
        json.put("nickname", nickname);
        sendEncryptedMessage(json.toString());

        new Thread(() -> {
            try {
                String encryptedMessage;
                while ((encryptedMessage = in.readLine()) != null) {
                    String decryptedMessage = decrypt(encryptedMessage);
                    chatArea.append(decryptedMessage + "\n");
                }
            } catch (Exception e) {
                chatArea.append("与服务器断开连接。\n");
            }
        }).start();
    }

    private void sendMessage(JTextField inputField, JTextArea chatArea) {
        String message = inputField.getText().trim();
        if (message.isEmpty()) return;

        inputField.setText("");
        try {
            JSONObject json = new JSONObject();
            json.put("message", message);
            sendEncryptedMessage(json.toString());
        } catch (Exception e) {
            chatArea.append("消息发送失败。\n");
        }
    }

    private void sendEncryptedMessage(String message) throws Exception {
        String encryptedMessage = encrypt(message);
        out.println(encryptedMessage);
    }

    private String encrypt(String data) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
    }

    private String decrypt(String data) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKeySpec key = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(Base64.getDecoder().decode(data)));
    }
}

posted on   shenhshihao  阅读(4)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示