I have to implemented a server which should accept more connections. Without any deeper thoughts I decided to use the new JAVA NIO.2 classes.
My current approach is:
final Semaphore wait = new Semaphore(1);
while(true){
wait.acquire();
this.asyncSocket.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
@Override
public void completed(AsynchronousSocketChannel result, Void attachment) {
wait.release();
asyncSocket.accept(null, this);
...
}
...
}
}
if I don't add the semaphore, I get an AcceptPendingException. It works, however, I don't know if that's the proper way to implement a server which can handle more open sockets.
Another approach was:
final Semaphore wait = new Semaphore(1);
while(true){
wait.acquire();
final Future<AsynchronousSocketChannel> futureChannel = this.asyncSocket.accept();
this.exec.execute(new Runnable() {
@Override
public void run() {
try (final AsynchronousSocketChannel clientChannel = futureChannel.get()) {
wait.release();
try (ObjectInputStream ois = new ObjectInputStream(Channels.newInputStream(clientChannel))) {
final Command cmd = (Command) ois.readObject();
cmd.execute(util, clientChannel, null, logger).run();
}
} catch (IOException | InterruptedException | ClassNotFoundException | ExecutionException e) {
e.printStackTrace();
}
}
});
Why I'm unhappy with both solutions? Unfortunately, in both implementations, the server leaves a lot of open sockets in state TIME_WAIT, although I'm closing the it on the server as well on the client side..
So actually I have 2 questions:
- What's a proper way to use
AsynchronousServerSocketChannelto implement a Server which accepts more connections. - How to get rid of the open sockets in state TIME_WAIT
EDIT:
private <T extends Serializable> T sendCommand(final Command<T> command) throws ExecutionException, InterruptedException, IOException, ClassNotFoundException {
T result = null;
try (final AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(channelGroup)) {
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
channel.connect(this.mwInfo.getNextMiddleware()).get();
final OutputStream os = Channels.newOutputStream(channel);
final InputStream is = Channels.newInputStream(channel);
try (final ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(command);
oos.flush();
try (final ObjectInputStream ois = new ObjectInputStream(is)) {
result = (T) ois.readObject();
}
}
}
return result;
}
Thanks in advance!