1. 程式人生 > 其它 >Java網路程式設計實現群聊

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();
            }
        }
    }