Issue
I've built simple client-server model using sockets. The server receives 1 type of request: 2 numbers from client, sums them, waits for 5 seconds and sends the response back to the client. I'm trying to send 20 asynchronous request from the client without waiting for response. The client should sums all the numbers from all the 20 Reponses from server. I'm trying to understand what should I use and how? Threads on the server, or the client and how? I've added my client and server classes. Server:
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);
}
}
}
Client:
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(); // (**)
}
}
}
Solution
Asynchronous means sending message and not waiting for response.
//Get the response message from server - so you wait whole 5 seconds for response :)
String responseMessage = reader.readLine();
The simplest solution in this case is to remove waiting for response each time. So, get rid of above lines from loop inside Client class.
In this particular client-sever case you do not need additional threads, if you would perform asynchronous things inside one application, then so. Take a look at Java Futures with some tutorial on how to use them. But if you want to get a result from server, you have to wait anyway. And you want to get results of all calcuations. Hence, you have to store all incoming requests somewhere. Simple, naive and impractical, but showing asynchronicity concept code may look like this
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 incoming 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);
}
}
}
Answered By - R-tooR
Answer Checked By - Terry (JavaFixing Volunteer)