I am writing a client with an integrated server that should wait indefinitely for new connections - and handle each on a Thread.
I want to process the received byte array in a system wide available message handler on the main thread. However, currently the processing is obviously done on the client thread.
I've looked at Futures, submit() of ExecutorService, but as I create my Client-Connections within the Server, the data would be returned to the Server thread. How can I return it from there onto the main thread (in a synchronized packet store maybe?) to process it without blocking the server?
My current implementation looks like this:
public class Server extends Thread {
private int port;
private ExecutorService threadPool;
public Server(int port) {
this.port = port;
// 50 simultaneous connections
threadPool = Executors.newFixedThreadPool(50);
}
public void run() {
try{
ServerSocket listener = new ServerSocket(this.port);
System.out.println("Listening on Port " + this.port);
Socket connection;
while(true){
try {
connection = listener.accept();
System.out.println("Accepted client " + connection.getInetAddress());
connection.setSoTimeout(4000);
ClientHandler conn_c= new ClientHandler(connection);
threadPool.execute(conn_c);
} catch (IOException e) {
System.out.println("IOException on connection: " + e);
}
}
} catch (IOException e) {
System.out.println("IOException on socket listen: " + e);
e.printStackTrace();
threadPool.shutdown();
}
}
}
class ClientHandler implements Runnable {
private Socket connection;
ClientHandler(Socket connection) {
this.connection=connection;
}
@Override
public void run() {
try {
// Read data from the InputStream, buffered
int count;
byte[] buffer = new byte[8192];
InputStream is = connection.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
// While there is data in the stream, read it
while ((count = is.read(buffer)) > 0) {
out.write(buffer, 0, count);
开发者_开发问答 }
is.close();
out.close();
System.out.println("Disconnect client " + connection.getInetAddress());
connection.close();
// handle the received data
MessageHandler.handle(out.toByteArray());
} catch (IOException e) {
System.out.println("IOException on socket read: " + e);
e.printStackTrace();
}
return;
}
}
Update: The robust way seems to be what TomTom suggested - using the newer java.nio instead. As this project is of limited use and more of an experiment, I'd like to know the best way using it with java.io/java.net :)
In my option, you can use a sync object to chat with the main thread, after your add client connections to the pool, the main thread can block at the accept and the sync object, after you client handle it, put the processed connection socket and response to a queue, and then wakeup the sync object, so the main thread can then get something from the queue and process it, after main thread handle it, block at accept and wait at the sync object.
Basically, your architecture is a simple/direct way, the newly way is use the java nio, to get the more concurrency server and get better performance, also the nio is not the best way...
That iwll not scale. Any reason you do that? Plus you waste tons of memory - you dont need a thread PER SOCKET. Use a better Java IO library. Like the one available as part of Java for like 10 years or so (NGIO?). It handles x threads with one socket, just returning data.
精彩评论