The code listens to a POST request continuously, and sends a response after fully reading the socket input data.
But it turns out that Java runtime automatically closes the readers and writers connected to the socket and to the standard input stream, and it closes the socket connection to the server, whenever it reaches an EOF while reading data as written in the Oracle documentation here.
I am reading data using this manner(reader is the 'client socket's input stream'):
while ((line = reader.readLine()) != null) {
requestData+=line+"\n";
}
This causes the reader to reach EOF, and causing all the socket reader and writers to close automatically, which i do not desire to happen. I need to know the requestData before i can send a response. Automatic closing of connected sockets prevents me from doing so.
Hence, everytime I try to open it from "http://192.168.129.185:9999/", the page keeps loading and loading, instead of displaying an output in plain text.
I need a workaround for this.
The full code is this:
import java.io.*;
import java.net.*;
class Server{
static int count= 0;
public static void main()throws Exception{
String address = "192.168.129.185";
int port = 9999;
ServerSocket serverSocket = new ServerSocket(port, 1, InetAddress.getByName(address));
while (true) {
Socket clientSocket = serverSocket.accept();
// Handle client connection in a separate thread (recommended)
new Thread(() -> handleClient(clientSocket)).start();
}
}
public static void handleClient(Socket clientSocket) {
try (PrintWriter writer = new PrintWriter(clientSocket.getOutputStream() , true);
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
//READ SOCKET DATA UNTIL EOF IS REACHED
String requestData = "";
int lineCount= 0;
String line;
while ((line = reader.readLine()) != null) {
requestData+=line+"\n";
lineCount++;
}
//when reader.readLine() reaches EOF, codes below this DO get executed, but NO response provided
String responseHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
// Write the response header and message
writer.print(responseHeader);
writer.print("{\"reply\":\""+count+"\"}");//ACTUAL RESPONSE DATA TO BE SENT
writer.flush();
count++;
} catch (IOException e) {
System.out.println("ERROR");
e.printStackTrace();
} finally {
// Close the client socket even on exceptions
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
finally{
}
}
}
}
[This is the current code which is causing the problem]
The function concerned from the above code is this:
public static void handleClient(Socket clientSocket) {
try (PrintWriter writer = new PrintWriter(clientSocket.getOutputStream() , true);
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
//READ SOCKET DATA UNTIL EOF IS REACHED
String requestData = "";
int lineCount= 0;
String line;
while ((line = reader.readLine()) != null) {
requestData+=line+"\n";
lineCount++;
}
//when reader.readLine() reaches EOF, codes below this DO get executed, but NO response provided
String responseHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
// Write the response header and message
writer.print(responseHeader);
writer.print("{\"reply\":\""+count+"\"}");//ACTUAL RESPONSE DATA TO BE SENT
writer.flush();
count++;
} catch (IOException e) {
System.out.println("ERROR");
e.printStackTrace();
} finally {
// Close the client socket even on exceptions
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
finally{
}
}
}
//READ SOCKET DATA UNTIL EOF IS REACHED
String requestData = "";
int lineCount= 0;
String line;
while ((line = reader.readLine()) != null & (lineCount <= 1)) {
requestData+=line+"\n";
lineCount++;
}
This snippet contains (lineCount <= 1)
in while loop causing it to check only the first line and avoids reaching EOF. This snippet makes code work perfectly. Upon sending request, it successfully returns the response as written in writer.print("{\"reply\":\""+count+"\"}");
.
Now, this isn't really useful, because i need to read the FULL socket input, and not just the first line.
This snippet is just a demonstration that the code in itself is working. Only the automatic closing sockets upon reaching EOF is a problem.
Your approach of reading until EOF is wrong from start. Instead you need to read the HTTP request header, parse it to extract the length of the expected body (i.e. either fixed length given by content-length header or several chunks with transfer-encoding chunked) and then read the body based on what length was given. The HTTP client will not close the connection after the request, it will wait for the servers response instead (or close after some timeout when no response is received).