import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
public class AsyncInternalDataServer {
private final int port;
private final Switchable dataHolder;
private AsynchronousServerSocketChannel serverSocketChannel;
private boolean running;
public AsyncInternalDataServer(int port, Switchable dataHolder) {
this.port = port;
this.dataHolder = dataHolder;
}
public void start() throws IllegalStateException, IOException {
if (this.running) throw new IllegalStateException("Server is already running");
else {
this.serverSocketChannel = AsynchronousServerSocketChannel.open();
this.serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
this.serverSocketChannel.bind(new InetSocketAddress(this.port));
serverSocketChannel.accept(null,
new AcceptCompletionHandler(this.serverSocketChannel, this.dataHolder));
this.running = true;
}
}
public void stop() throws IllegalStateException, IOException {
if (!this.running) throw new IllegalStateException("Server is not running yet");
else {
this.serverSocketChannel.close();
this.running = false;
}
}
private static class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Void> {
private final AsynchronousServerSocketChannel serverSocketChannel;
private final Switchable dataHolder;
AcceptCompletionHandler(AsynchronousServerSocketChannel serverSocketChannel, Switchable dataHolder) {
this.serverSocketChannel = serverSocketChannel;
this.dataHolder = dataHolder;
}
@Override
public void completed(AsynchronousSocketChannel socketChannel, Void attachment) {
this.serverSocketChannel.accept(null, this);
WriteCompletionHandler writeCompletionHandler = new WriteCompletionHandler(socketChannel);
ByteBuffer buffer;
synchronized (this.dataHolder) {
buffer = ByteBuffer.allocate(1).put((byte) (this.dataHolder.isEnabled() ? 1 : 0));
}
socketChannel.write((ByteBuffer) buffer.flip(), null, writeCompletionHandler);
}
@Override
public void failed(Throwable exc, Void attachment) {
if (exc instanceof AsynchronousCloseException) {
System.out.println("Waiting for an incoming connection canceled : Server closed");
} else {
System.err.println("Accepting an incoming connection failed");
exc.printStackTrace();
}
}
}
private static class WriteCompletionHandler implements CompletionHandler<Integer, Void> {
private final AsynchronousSocketChannel socketChannel;
WriteCompletionHandler(AsynchronousSocketChannel socketChannel) {
this.socketChannel = socketChannel;
}
@Override
public void completed(Integer result, Void attachment) {
try {
this.socketChannel.close();
} catch (IOException ioException) {
System.err.println("Cannot close client socket");
ioException.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Void attachment) {
System.err.println("Data sending failed");
exc.printStackTrace();
}
}
}