使用Java socket 簡單實現實時通信,單聊,羣聊功能

  1. 一對一單聊的實現:客戶端帶着發送方ID和接收方ID、信息發送給服務端,服務端從socket池中找出接收方ID進行轉發。
  2. 羣發的實現:客戶端發送羣發消息給服務端,然後服務端從socket池中取出所有正在連接的客戶端,然後進行轉發
import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.UUID;

public class socket {

    static java.util.Map<String, Socket> socketMap = new HashMap<>();

    public static void main(String[] args) throws InterruptedException {


        Thread server = new Thread(() -> {

            try {
                ServerSocket serverSocket = new ServerSocket(6666);
                while (true) {
                    Socket socket = serverSocket.accept();
                    serverRead(socket);
                    

                }
            } catch (IOException e) {
                System.out.println("報錯了");
                e.printStackTrace();
            }


        });
        server.join();
        server.start();




        mySocket b = clientConServer();
        
        mySocket a =  clientConServer();

        
        try {
            clientSend(a,"你好",b.id);
            Thread.sleep(1000);

            clientSend(b,"你也好",a.id);
            Thread.sleep(1000);
            clientSendAll(a,"大家好");
        } catch (IOException e) {
            e.printStackTrace();
        }
        Thread.sleep(1000);
        disconnect(a);

        Thread.sleep(1000);
        disconnect(b);
        try {
            a.socket.close();
            b.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    /**
     * 客戶端與服務端建立連接   C
     */
    public static mySocket clientConServer() {
            mySocket socket = new mySocket();
            try {
                PrintWriter printWriter = new PrintWriter(socket.socket.getOutputStream());
                printWriter.write("connect\n");
                printWriter.flush();
                printWriter.write(socket.id+"\n");
                printWriter.flush();
                readThread(socket.socket);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return socket;
    }


    /**
     * 服務器監聽  S
     */
    public static void serverRead(Socket socket) throws IOException {
        //開啓服務器輸入監聽線程
        SocketInterface socketRead = (Socket socket1) -> {
            Thread thread = new Thread() {
                public Socket socket = socket1;
                String info;

                @Override
                public void run() {
                    try {
                        //獲取輸入流
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket1.getInputStream()));

                        while ((info = bufferedReader.readLine()) != null) {

                            //如果監聽到連接指令:connect,則獲取socketId,並將此socket連接保存到靜態map中
                            if (info.equals("connect")) {
                                //獲取socketId
                                String key = bufferedReader.readLine();
                                //存入在靜態Map中
                                socketMap.put(key, socket);
                                //回傳給客戶端,提示已經建立連接
                                PrintWriter we = new PrintWriter(socket.getOutputStream());
//                                System.out.println(key);
                                we.write("客戶端" + key + "連接服務器成功\n");
                                we.flush();
                            }
                            //如果監聽到連接指令:send,則獲取發送客戶端socketId:from,接受客戶端socketId:to,發送的消息:message
                            if ("send".equals(info)){
                                //發送客戶端socketId
                               String from = bufferedReader.readLine();
                               //接受客戶端socketId
                               String to = bufferedReader.readLine();
                               //發送
                               send(from,bufferedReader.readLine(),to);
                            }
                            //如果監聽到連接指令:sendAll,則羣發消息
                            if ("sendAll".equals(info)){
                                String from = bufferedReader.readLine();
                                String message = bufferedReader.readLine();
                                mass(message,from);
                            }
                            //如果監聽到連接指令:disconnect,則斷開與某個客戶端的連接
                            if ("disconnect".equals(info)){
                                String from = bufferedReader.readLine();
                                info = from;
                                System.out.println(from+"請求斷開連接");

                                socketMap.get(from).getOutputStream().close();
                                socketMap.get(from).getInputStream().close();
                                socketMap.get(from).close();
                                
                            }
//                            System.out.println(info);

                        }
                    } catch (SocketException se) {
                        System.out.println(info+"已斷開");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            thread.start();
        };
        socketRead.read(socket);
    }


    /**
     * 客戶端接受信息  C
     *
     * @param socket
     */
    public static void readThread(Socket socket) {
        //開啓客戶端輸入監聽線程
        SocketInterface socketRead = (Socket socket1) -> {
            Thread thread = new Thread() {
                public Socket socket = socket1;
                public String info = null;

                @Override
                public void run() {
                    try {
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket1.getInputStream()));
                        while ((info = bufferedReader.readLine()) != null) {
                            System.out.println(info);
                        }
                    } catch (SocketException se) {
                        System.out.println("socket關閉");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            thread.start();

        };
        socketRead.read(socket);
    }

    /**
     * 服務器轉發羣發消息  S
     *
     * @param message
     */
    
    public static void mass(String message, String fromUUID) {
        //遍歷所有已連接服務器的socket
        socketMap.forEach((s, socket) -> {
            if (!socket.isClosed()) {
                try {
//                    發送信息
                    PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
                    printWriter.write( s+"收到來自<---"+fromUUID + "的羣發消息:" + message + "\n");
                    printWriter.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 客戶端發送給客戶端  C
     * @param a
     * @param message
     * @param to
     * @throws IOException
     */
    public static void clientSend(mySocket a,String message,String to) throws IOException {
        PrintWriter printWriter = new PrintWriter(a.socket.getOutputStream());
        printWriter.write("send\n");
        printWriter.flush();
        printWriter.write(a.id+"\n");
        printWriter.flush();
        printWriter.write(to+"\n");
        printWriter.flush();
        printWriter.write(message+"\n");
        printWriter.flush();
    }

    /**
     * 客戶端羣發消息 C
     * 
     * @param a
     * @param message
     * @throws IOException
     */
    public static void clientSendAll(mySocket a,String message) throws IOException {
        PrintWriter printWriter = new PrintWriter(a.socket.getOutputStream());
        printWriter.write("sendAll\n");
        printWriter.flush();
        printWriter.write(a.id+"\n");
        printWriter.flush();
        printWriter.write(message+"\n");
        printWriter.flush();
    }
    /**
     * 服務器轉發 S
     * @param from
     * @param message
     * @param to
     * @throws IOException
     */
    
    public static void send(String from,String message,String to) throws IOException {
        //從socket池中獲取接受客戶端socket,並寫入信息
        PrintWriter printWriter  = new PrintWriter(socketMap.get(to).getOutputStream());
        printWriter.write(to+"\n");
        printWriter.flush();
        printWriter.write(from+"發送給-->"+to+":"+message+"\n");
        printWriter.flush();
    }


   

    /**
     *
     * 斷開連接  C
     */
    static void disconnect(mySocket mySocket){
        try {
            PrintWriter printWriter = new PrintWriter(mySocket.socket.getOutputStream());
            printWriter.write("disconnect\n");
            printWriter.flush();
            printWriter.write(mySocket.id+"\n");
            printWriter.flush();
            
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

 




}

 

 static class mySocket {
        public String id;
        public Socket socket;

        mySocket() {
            this.id = UUID.randomUUID().toString();
            try {
                this.socket = new Socket("192.168.157.1", 6666);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

 接口類

import java.net.Socket;

public interface SocketInterface {
    /**
     * 開啓監聽
     */
    void read(Socket socket);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章