Java网络编程实现群聊


Java网络编程实现群聊

服务器

服务器网络应用负责客户端消息的接发与验证

  • 接发消息的实体

    /**
     * 中央分发数据
     */
    public class CenterData {
    
        // 数据自身
        private static String date;
    
        // 获取数据
        public static String getDate() {
            return date;
        }
    
        // 封装数据
        public static void setDate(String date) {
    
            if (date.contains("傻子") || date.contains("sb")) {
    
                // 通过正则表达式替换危险词语
                CenterData.date = date.replaceAll("[傻子|sb]", "*");
            } else {
                CenterData.date = date;
            }
        }
        
    }
    
  • 服务端消息接受线程

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
    
    /**
     * 服务器消息接受线程
     */
    public class ServerChatReceiveThread implements Runnable {
    
        private Socket socket;
    
        public ServerChatReceiveThread(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
    
            this.receiveMsg();
        }
    
        /**
         * 接受消息的方法
         */
        private void receiveMsg() {
    
            // 用于接受消息
            BufferedReader br = null;
    
            try {
    
                // 初始化 接受消息 的 字符流
                br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
    
                // 不停的接受消息
                while (true) {
    
                    // 读取客户端的消息
                    String msg = br.readLine();
    
                    // 同步锁 同步 消息中央仓库
                    // 字符串常量池锁
                    synchronized ("abc") {
    
                        // 存入中央仓库消息
                        CenterData.setData(msg);
    
                        // 通知发送线程
                        "abc".notifyAll();
                    }
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (null != br) {
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != this.socket) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    }
    
  • 服务器发送消息线程

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    /**
     * 消息发送线程
     */
    public class ServerChatSendThread implements Runnable {
    
        private Socket socket;
    
        public ServerChatSendThread(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            this.sendMsg();
        }
    
        /**
         * 发送消息
         */
        private void sendMsg() {
    
            PrintWriter pw = null;
    
            try {
                // 初始化 字符输出流
                pw = new PrintWriter(this.socket.getOutputStream());
    
                // 一直发送消息
                while (true) {
    
                    // 进入同步状态
                    synchronized ("abc") {
    
                        // 发送消息的线程先等待 等待接受线程的叫醒
                        "abc".wait();
    
                        // 发送消息
                        pw.println("[" + this.socket.getInetAddress() + "]说:" + CenterData.getData());
                        pw.flush();
                    }
                }
    
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (null != pw) {
                    pw.close();
                }
                if (null != this.socket) {
                    try {
                        this.socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
  • 服务器主线程

    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 群聊服务器
     */
    public class ChatRoomServer {
    
        public static void main(String[] args) {
    
            System.out.println("------群聊服务器已经创建------");
            System.out.println("------服务器监听的端口为:8088------");
            System.out.println("--------------------------------");
    
            // 创建连接对象
            ServerSocket serverSocket = null;
    
            try {
    
                // 初始化连接对象的监听端口
                serverSocket = new ServerSocket(8088);
    
                // 不停的监听 阻塞
                while (true) {
    
                    // 进入阻塞状态
                    Socket socket = serverSocket.accept();
    
                    // 进入非阻塞状态
                    System.out.println("------>>>服务器日志:" + socket.getInetAddress() + "连接到服务器");
    
                    // 开启此时的客户端读线程
                    new Thread(new ChatReceiveThread(socket)).start();
    
                    // 开启此时的客户端写线程
                    new Thread(new ChatSendThread(socket)).start();
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (null != serverSocket){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    }
    

客户端

  • 客户端发送消息线程

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.util.Scanner;
    
    /**
     * 客户端发送消息线程
     */
    public class ClientChatSendThread implements Runnable {
    
        // 客户端对象
        private Socket socket;
    
        // 键盘对象
        private Scanner scanner;
    
    
        public ClientChatSendThread(Socket socket, Scanner scanner) {
            this.socket = socket;
            this.scanner = scanner;
        }
    
    
        @Override
        public void run() {
    
            // 启动线程 启动发送消息方法
            this.sendMsg();
        }
    
        /**
         * 发送消息方法
         */
        private void sendMsg() {
    
            PrintWriter pw = null;
    
            try {
    
                pw = new PrintWriter(this.socket.getOutputStream());
    
                while (true) {
    
                    System.out.println("请输入要发送的消息:");
                    String msg = scanner.nextLine();
    
                    // 向服务器发送消息
                    pw.println(msg);
                    pw.flush();
    
                    // 结束客户端
                    if ("bye".equals(msg)) {
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (scanner != null) {
                    scanner.close();
                }
                if (pw != null) {
                    pw.close();
                }
                if (socket != null) try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
  • 客户端接受消息线程

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
    
    /**
     * 客户端接受消息线程
     */
    public class ClientChatReceiveThread implements Runnable{
    
        // 客户端对象
        private Socket socket;
    
        public ClientChatReceiveThread(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            this.receiveMsg();
        }
    
        private void receiveMsg() {
    
            BufferedReader br = null;
    
            try {
    
                br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
    
                while (true) {
    
                    String msg = br.readLine();
                    System.out.println(msg);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (br != null) br.close();
                    if (socket != null) socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
  • 客户端主线程

    import java.io.IOException;
    import java.net.Socket;
    import java.util.Scanner;
    
    /**
     * 群聊客户端
     */
    public class ChatRoomClient {
    
        public static void main(String[] args) {
    
            // 客户端对象
            Socket socket = null;
    
            // 键盘输入对象
            Scanner scanner = null;
    
            try {
    
                // 初始化键盘输入对象
                scanner = new Scanner(System.in);
    
                // 写死群聊服务器地址 局域网中确定一个C类网址
                socket = new Socket("192.168.2.106", 8088);
                System.out.println("=====群聊服务器连接成功=====");
    
                // 启动发送消息线程
                new Thread(new ClientChatSendThread(socket, scanner)).start();
                // 启动接受消息线程
                new Thread(new ClientChatReceiveThread(socket)).start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }