簡體   English   中英

如何從客戶端向服務器發送多個異步請求

[英]How to send multiple of asynchronous requests from client to server

我使用 sockets 構建了簡單的客戶端服務器 model。 服務器收到 1 種類型的請求:來自客戶端的 2 個數字,將它們相加,等待 5 秒並將響應發送回客戶端。 我正在嘗試從客戶端發送 20 個異步請求而不等待響應。 客戶端應將來自服務器的所有 20 個響應中的所有數字相加。 我試圖了解我應該使用什么以及如何使用? 服務器上的線程,或者客戶端又如何? 我已經添加了我的客戶端和服務器類。 服務器:

public  class Server {
    public static void main(String[] args) throws IOException {
        try {
            //Make a ServerSocket to listen for message
            ServerSocket ss = new ServerSocket(7777);

            while (true == true) {
                //Accept input from socket
                Socket s = ss.accept();

                //Read input from socket
                InputStreamReader streamReader = new InputStreamReader(s.getInputStream());
                BufferedReader reader = new BufferedReader(streamReader);
                String message = reader.readLine();
                System.out.println(message);
                //parse the json recieved from client and sum the 2 numbers
                Object obj = new JSONParser().parse(String.valueOf(message));
                JSONObject jo = (JSONObject) obj;
                long num1 = (long) jo.get("num1");
                long num2 = (long) jo.get("num2");
                long sum = num1 + num2;
                Thread.sleep(5000);

                //putting response as json
                JSONObject jsonResponse = new JSONObject();
                jsonResponse.put("response", sum);
                //get the message and write it to the socket as response
                PrintWriter writer = new PrintWriter(s.getOutputStream());
                writer.println(jsonResponse);
                //System.out.println(df);
                writer.close();
            }
        } catch (IOException | ParseException | InterruptedException ex) {
            System.out.println(ex);
        }
    }
}

客戶:

public  class Client {
    public static void main(String[] args) throws IOException {
        try {
            //this variable will sum all the responses from server
            long sumOfAllResponses = 0;
            
            for(int i = 0 ; i< 20; i++){
                //Create a Socket with ip and port number
                Socket s = new Socket("localhost", 7777);
                Scanner in = new Scanner(System.in);
                PrintWriter writer = new PrintWriter(s.getOutputStream());
                InputStreamReader streamReader = new InputStreamReader(s.getInputStream());
                BufferedReader reader = new BufferedReader(streamReader);
                //Creating json with 2 numbers to be sent to server as a request
                JSONObject jsonRequest = new JSONObject();
                jsonRequest.put("num1", 1);
                jsonRequest.put("num2", 1);
                System.out.println(jsonRequest);
                //Make a printWriter and write the message to the socket
                writer.println(jsonRequest);
                writer.flush();
                //Get the response message from server
                String responseMessage = reader.readLine();
                //parse the response and add the result to the sum variable
                Object obj = new JSONParser().parse(String.valueOf(responseMessage));
                JSONObject jo = (JSONObject) obj;
                sumOfAllResponses += (long) jo.get("response");
            }
            System.out.println(sumOfAllResponses);
        }
        catch (IOException | ParseException ex) {
            ex.printStackTrace(); // (**)
        }
    }
}

服務器端

服務器不應在其主線程上處理請求。 相反,它應該為它收到的每個請求打開處理線程。

我們應該限制並發運行的線程數。

這是簡單的代碼示例:

public class Server {
    private static final int NUMBER_OF_CONCURRENT_THREADS = 20;
    private ServerSocket serverSocket;
    ExecutorService executor = Executors.newFixedThreadPool(NUMBER_OF_CONCURRENT_THREADS);

    public void start(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true) {

            final Socket clientSocket = serverSocket.accept();
            final ClientHandler clientHandler = new ClientHandler(clientSocket);
            executor.submit(clientHandler);
        }
    }

    public void stop() throws IOException {
        serverSocket.close();
    }

    private static class ClientHandler implements Runnable {
        private Socket clientSocket;

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

        public void run() {
            // Implement your client logic here
        }
    }
}

客戶端

現在您可以同時從客戶端發送您的請求,它們將由服務同時處理(一次最多 20 個請求)

我將把並發請求發送的實現留給你,但這里有一些指導方針:

  • 你可以在它自己的線程中發送每個請求,使用 ExecutorService 來處理這些線程
  • 對於來自服務的每個響應,添加到包含所有響應總和的共享變量。
  • 確保同步對共享總和的訪問,因為多個線程將並行更新它。

異步意味着發送消息而不等待響應。

            //Get the response message from server - so you wait whole 5 seconds for response :)
            String responseMessage = reader.readLine();

這種情況下最簡單的解決方案是每次都去掉等待響應。 因此,從客戶端 class 內的循環中刪除上述行。

在這種特定的客戶端-服務器情況下,您不需要額外的線程,如果您要在一個應用程序中執行異步操作,那么就可以。 查看Java Futures以及一些關於如何使用它們的教程 但是,如果您想從服務器獲取結果,則無論如何都必須等待。 你想得到所有計算的結果。 因此,您必須將所有傳入請求存儲在某處。 簡單、幼稚且不切實際,但顯示異步概念的代碼可能看起來像這樣

public class Client {
  public static void main(String[] args) throws IOException {
    try {
        long start = System.currentTimeMillis();
        BufferedReader reader = null;
        for(int i = 0 ; i < 20; i++){
            Socket s = new Socket("localhost", 7777);
            PrintWriter writer = new PrintWriter(s.getOutputStream());
            InputStreamReader streamReader = new InputStreamReader(s.getInputStream());
            reader = new BufferedReader(streamReader);
            // just make sure you send data and do not wait for response
            System.out.println("Sending " + i  + " : " + (System.currentTimeMillis() - start)); 
            writer.println(i);
            writer.flush();
        }
        //this line works like future.get(), it hangs client until it receives result
        String responseMessage = reader.readLine();
        // process returned data as you want
        System.out.println(responseMessage);
    }
    catch (IOException ex) {
        ex.printStackTrace(); // (**)
    }
  }
}

public class Server {
  public static void main(String[] args) throws IOException {
    try {
        //Make a ServerSocket to listen for message
        ServerSocket ss = new ServerSocket(7777);
        Socket s;
        //we need to store incomming requests to process, and return them
        List<String> integerList = new LinkedList<>();
        while (true) {
            s = ss.accept();

            InputStreamReader streamReader = new InputStreamReader(s.getInputStream());
            BufferedReader reader = new BufferedReader(streamReader);
            String message = reader.readLine();
            System.out.println(message);
            // do something here
            
            Thread.sleep(5000);

            PrintWriter writer = new PrintWriter(s.getOutputStream());
            integerList.add(message);
            writer.println(integerList);
            writer.close();
        }
    } catch (IOException | InterruptedException ex) {
        System.out.println(ex);
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM