I am currently testing a Java server that I am writing, which is not actually going to be an HTTP server, but for now I am trying to output the client request data received from a browser into the console, and then send a response to the browser, which displays the text I sent in the browser window. I'm following a tutorial from jenkov.com but I'm trying to create an abstract ConnectionHandler to handle all requests on a particular server. Here is my code so far:
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);
}
Output in console with the request reading code (but browser hangs and page doesn't load):
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
I guess I want to know if I am doing this right. I really would like to be able to have a single connection handler that works correctly on multiple threads that can be defined inside the TestClient. I'm not sure if I'm supposed to synchronize the ConnectionHandler inside Server.java because I only have one handler that will be access by each thread handling a connection. Please help me figure out what I am doing wrong, I'm kind of new to Java threads...thanks.