1. 程式人生 > >Socket多客戶端通訊

Socket多客戶端通訊

    服務端首先構造的是ServerSocket 物件,傳入構造方法中的引數是埠號,同需連線客戶端的埠號一致。接下來通過ServerSocket 物件的accept()方法來獲取Socket物件,此方法被稱為阻塞方法,該一直在執行,等待客戶端傳送的Socket連線請求,若未收到請求,accept()方法就一直在迴圈執行,始終不返回結果,直到收到請求後,accept()方法會返回傳送請求的Socket 物件。

/**
 * Socket多客戶端通訊---服務端
 */
public class MultiTalkServer {
    static int clientNum = 0;
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        boolean listening = true;
        try {
            serverSocket = new ServerSocket(1234);
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (listening){
            Socket socket = serverSocket.accept();
            new ServerThread(socket,clientNum).start();
            clientNum++;
        }
        serverSocket.close();
    }

    public static class ServerThread extends Thread{
        Socket socket = null;
        int clientNum;
        private ServerThread(Socket socket,int num){
            this.socket = socket;
            this.clientNum = num+1;
        }

        @Override
        public void run() {
            try {
                BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
                PrintWriter sendStream = new PrintWriter(socket.getOutputStream());
                BufferedReader recvStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                System.out.println("Client:" + clientNum +" " + recvStream.readLine());

                String str = input.readLine();
                while (!str.equals("886")){
                    sendStream.println(str);
                    sendStream.flush();
                    System.out.println("Server:" + str);
                    System.out.println("Client:" + clientNum+" " + recvStream.readLine());
                    str = input.readLine();
                }
                sendStream.close();
                recvStream.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

   服務端 類中有個靜態成員變數clientNum用來記錄發起請求的客戶端數量,構造ServerSocket物件,在while迴圈方法體建立ServerThread執行緒。相當於main 方法一直在迴圈等待客戶端socket請求,一旦接收到socket請求,就例項化一個執行緒與之互動聊天,執行緒記錄數量加一。

ServerThread的實現,內部維護了socket物件和客戶端數量,run 方法中首先建立了三個流:

  • 一個輸入流獲取鍵盤輸入,
  • 再用輸出流將資訊傳送給對方網路,
  • 最後構造一個輸入流獲取響應的資訊。

接下來判斷鍵盤輸入文字為“886”則停止傳送,聊天結束;否則繼續讀取鍵盤輸入流傳送資訊,最後關閉流和socket的連線。

一個客戶端程式碼如下:多個可相同

public class TalkClient {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1",1234);
            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
            PrintWriter sendStream = new PrintWriter(socket.getOutputStream());
            BufferedReader recvStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            String str = input.readLine();
            while (!str.equals("886")){
                sendStream.println(str);
                sendStream.flush();
                System.out.println("Client: " + str);
                System.out.println("Server:" + recvStream.readLine());
                str = input.readLine();
            }
            sendStream.close();
            recvStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服務端與客戶端的例子很大部分內容相同,只是服務端需要構造一個ServerSocket,通過ServerSocket得到和客戶端連線的Socket物件,得到物件後可以構造輸入、出流進行IO流的讀寫,最後關閉流、Socket即可。