Java 线程池服务器:我只能读取请求或成功发送响应,但不能同时读取两者
Java Thread-pooled server: I am only able to either read the request, or successfully send a response, but not both
我目前正在测试我正在编写的 Java 服务器,它实际上并不是一个 HTTP 服务器,但现在我正在尝试将从浏览器接收到的客户端请求数据输出到控制台,然后向浏览器发送一个响应,它会显示我在浏览器中发送的文本window。我正在学习 jenkov.com 的教程,但我正在尝试创建一个抽象的 ConnectionHandler 来处理特定服务器上的所有请求。到目前为止,这是我的代码:
TestClient.java
public class TestClient {
public static void main(String[] args) {
Server messageServer = new Server(80);
messageServer.start(new ConnectionHandler() {
@Override
public void request(InputStream req, OutputStream res) {
try {
// When I comment out the code for reading from req, then the response
// successfully sends, but if I try to read the request and output it to
// to the console, it hangs forever
BufferedReader reader = new BufferedReader(new InputStreamReader(req));
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
reader.close();
long time = System.currentTimeMillis();
res.write(("HTTP/1.1 200 OK\n\nWorkerRunnable: " +
"Multithreaded Server" + " - " +
time +
"").getBytes());
res.close();
System.out.println("Request processed: " + time);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
Server.java:
public class Server implements Runnable {
private int port;
private Thread runningThread = null;
private ServerSocket ss = null;
private boolean running = false;
private ExecutorService threadPool = Executors.newFixedThreadPool(100);
private ConnectionHandler handler;
public Server(int port) {
this.port = port;
}
public void start(ConnectionHandler handler) {
this.handler = handler;
this.running = true;
new Thread(this).start();
}
public synchronized boolean isRunning() {
return running;
}
public synchronized void stop() {
this.running = false;
try {
this.ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
try {
this.ss = new ServerSocket(this.port);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Listening on port " + this.port + "...");
while (this.isRunning()) {
Socket client;
try {
client = this.ss.accept();
System.out.println("Incoming connection from " + client.getRemoteSocketAddress());
} catch (IOException e) {
if (!this.isRunning()) {
System.out.println("The server stopped.");
return;
}
e.printStackTrace();
continue;
}
this.threadPool.execute(new ClientHandler(client, this.handler));
}
this.threadPool.shutdown();
}
}
ClientHandler.java:
public class ClientHandler implements Runnable {
private Socket sock = null;
private String serverText = "Multithreaded Server";
private ConnectionHandler handler;
public ClientHandler(Socket sock, ConnectionHandler handler) {
this.sock = sock;
this.handler = handler;
}
public void run() {
try {
this.handler.request(this.sock.getInputStream(), this.sock.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
ConnectionHandler.java:
public abstract class ConnectionHandler {
public abstract void request(InputStream req, OutputStream res);
}
控制台输出请求读取代码(但浏览器挂起且页面未加载):
Listening on port 80...
Incoming connection from /0:0:0:0:0:0:0:1:59404
GET / HTTP/1.1
Host: localhost
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ...
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: ...
Upgrade-Insecure-Requests: 1
我想我想知道我这样做是否正确。我真的很希望能够有一个连接处理程序,它可以在可以在 TestClient 中定义的多个线程上正常工作。我不确定是否应该同步 Server.java 内的 ConnectionHandler,因为我只有一个处理程序,每个处理连接的线程都可以访问该处理程序。请帮我弄清楚我做错了什么,我是 Java 线程的新手...谢谢。
我似乎找到了问题的答案here。看起来,当从请求流中读取一行时,您必须编写如下内容:
while ((line = reader.readLine()) != null && !line.equals(""))
System.out.println(line);
这似乎解决了我的问题!
我目前正在测试我正在编写的 Java 服务器,它实际上并不是一个 HTTP 服务器,但现在我正在尝试将从浏览器接收到的客户端请求数据输出到控制台,然后向浏览器发送一个响应,它会显示我在浏览器中发送的文本window。我正在学习 jenkov.com 的教程,但我正在尝试创建一个抽象的 ConnectionHandler 来处理特定服务器上的所有请求。到目前为止,这是我的代码:
TestClient.java
public class TestClient {
public static void main(String[] args) {
Server messageServer = new Server(80);
messageServer.start(new ConnectionHandler() {
@Override
public void request(InputStream req, OutputStream res) {
try {
// When I comment out the code for reading from req, then the response
// successfully sends, but if I try to read the request and output it to
// to the console, it hangs forever
BufferedReader reader = new BufferedReader(new InputStreamReader(req));
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
reader.close();
long time = System.currentTimeMillis();
res.write(("HTTP/1.1 200 OK\n\nWorkerRunnable: " +
"Multithreaded Server" + " - " +
time +
"").getBytes());
res.close();
System.out.println("Request processed: " + time);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
Server.java:
public class Server implements Runnable {
private int port;
private Thread runningThread = null;
private ServerSocket ss = null;
private boolean running = false;
private ExecutorService threadPool = Executors.newFixedThreadPool(100);
private ConnectionHandler handler;
public Server(int port) {
this.port = port;
}
public void start(ConnectionHandler handler) {
this.handler = handler;
this.running = true;
new Thread(this).start();
}
public synchronized boolean isRunning() {
return running;
}
public synchronized void stop() {
this.running = false;
try {
this.ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
try {
this.ss = new ServerSocket(this.port);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Listening on port " + this.port + "...");
while (this.isRunning()) {
Socket client;
try {
client = this.ss.accept();
System.out.println("Incoming connection from " + client.getRemoteSocketAddress());
} catch (IOException e) {
if (!this.isRunning()) {
System.out.println("The server stopped.");
return;
}
e.printStackTrace();
continue;
}
this.threadPool.execute(new ClientHandler(client, this.handler));
}
this.threadPool.shutdown();
}
}
ClientHandler.java:
public class ClientHandler implements Runnable {
private Socket sock = null;
private String serverText = "Multithreaded Server";
private ConnectionHandler handler;
public ClientHandler(Socket sock, ConnectionHandler handler) {
this.sock = sock;
this.handler = handler;
}
public void run() {
try {
this.handler.request(this.sock.getInputStream(), this.sock.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
ConnectionHandler.java:
public abstract class ConnectionHandler {
public abstract void request(InputStream req, OutputStream res);
}
控制台输出请求读取代码(但浏览器挂起且页面未加载):
Listening on port 80...
Incoming connection from /0:0:0:0:0:0:0:1:59404
GET / HTTP/1.1
Host: localhost
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ...
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: ...
Upgrade-Insecure-Requests: 1
我想我想知道我这样做是否正确。我真的很希望能够有一个连接处理程序,它可以在可以在 TestClient 中定义的多个线程上正常工作。我不确定是否应该同步 Server.java 内的 ConnectionHandler,因为我只有一个处理程序,每个处理连接的线程都可以访问该处理程序。请帮我弄清楚我做错了什么,我是 Java 线程的新手...谢谢。
我似乎找到了问题的答案here。看起来,当从请求流中读取一行时,您必须编写如下内容:
while ((line = reader.readLine()) != null && !line.equals(""))
System.out.println(line);
这似乎解决了我的问题!