代码持续侦听 POST 请求,并在完全读取套接字输入数据后发送响应。
但事实证明,Java 运行时会自动关闭连接到套接字和标准输入流的读取器和写入器,并且每当在读取数据时达到 EOF(如 Oracle 文档中所述)时,它就会关闭与服务器的套接字连接这里.
我正在使用这种方式读取数据(reader是'客户端套接字的输入流'):
while ((line = reader.readLine()) != null) {
requestData+=line+"\n";
}
这会导致读取器到达 EOF,并导致所有套接字读取器和写入器自动关闭,这是我不希望发生的情况。在发送响应之前,我需要知道 requestData。自动关闭连接的套接字阻止我这样做。
因此,每次我尝试从“http://192.168.129.185:9999/”打开它时,页面都会不断加载,而不是以纯文本显示输出。
我需要一个解决方法。
完整代码是这样的:
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{
}
}
}
}
[这是导致问题的当前代码]
上面代码中涉及到的函数是这样的:
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++;
}
此片段在 while 循环中包含
(lineCount <= 1)
,导致它仅检查第一行并避免到达 EOF。这段代码使代码完美运行。发送请求后,它成功返回响应,如writer.print("{\"reply\":\""+count+"\"}");
中所示。
现在,这并不是很有用,因为我需要读取完整的套接字输入,而不仅仅是第一行。
此片段只是代码本身正在运行的演示。只有达到 EOF 时自动关闭套接字才是问题。
您阅读直到 EOF 的方法从一开始就是错误的。相反,您需要读取请求标头,解析它以提取预期正文的长度(即内容长度标头给出的固定长度或传输编码分块的几个块),然后根据给定的长度读取正文。客户端在请求后不会关闭连接,而是等待服务器响应(或在未收到响应时超时后关闭)。