Current server implementation uses traditional socket, one of disadvantages is that it cannot reuse socket in single thread mode, as SocketServer.accept() will block current thread.
So NioServer is implemented.
NioServer uses Java NIO to monitor multiple sockets at the same time. The implementation is pretty straightforward.
public void start() {
try {
server = ServerSocketChannel.open();
server.configureBlocking(false);
SocketAddress address = new InetSocketAddress(host, port);
server.socket().bind(address);
selector = SelectorProvider.provider().openSelector();
server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Jimds is ready to accept requests on port " + port);
int times = 0;
while (!stop.get()) {
while (selector.select(1000) > 0 && !stop.get()) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
if (selectionKey.isAcceptable()) {
ServerSocketChannel nextReady = (ServerSocketChannel) selectionKey.channel();
SocketChannel channel = nextReady.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
process(socketChannel);
}
iterator.remove();
}
}
times++;
if (times % 10 == 0) {
times = 0;
requestMeasureCollector.print();
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
the process() method is similiar with BioServer.
But in order to support both Socket and Channel, two interfaces, DataReader and DataWriter are provided, and CommandReader now uses DataReader to read data.
public interface DataReader {
Byte peek() throws IOException;
void skip(int bytes) throws IOException;
byte[] read(int len) throws IOException;
List<byte[]> readUntilStop() throws IOException;
}
public interface DataWriter {
void write(byte[] buf) throws IOException;
void write(byte[] buf, int offset, int size) throws IOException;
}