Java Network Programming--AIO Asynchronous Network Programming

Keywords: Java Linux socket Windows Netty

A in AIO is Asynchronous, AIO is asynchronous IO. It is asynchronous and non-blocking. The client's I/O requests are processed by the OS and then the server application is notified to start the thread. Generally, our business processing logic will become a callback function, waiting for the IO operation to be completed and triggered automatically by the system.

When reading and writing operations are performed, only the read/write method of the API needs to be invoked directly. Both methods are asynchronous. For the read operation, when there is stream readable, the operating system will pass the readable stream into the buffer of the read method and notify the application. For the write operation, the operating system will actively notify the application when the flow passed by the write method has been written. It can be understood that the read/write method is asynchronous and callback function will be called actively after completion.

AIO is actually an enhancement of NIO, with many new classes supporting asynchrony, such as Asynchronous Server Socket Channel, Asynchronous Channel, Asynchronous Channel Group, Completion Handler, etc.

The underlying implementations of AIO and NIO in Linux system are epoll. epoll itself is a polling model. AIO is just another layer of epoll. In windows system, AIO is implemented by IOCP (Completion Port). At present, most servers are Linux systems, which is one of the reasons why Netty uses NIO instead of AIO. In practice, because of the differences in operating systems, the performance of AIO is sometimes not NIO efficient, so the use of AIO is not very extensive.

Sample AIO server-side code:

public class AIOServer {

  public static void main(String[] args) throws IOException {

    // Multithread version
    //    ExecutorService executorService = Executors.newCachedThreadPool();
    //    AsynchronousChannelGroup channelGroup =
    //        AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);
    //      AsynchronousServerSocketChannel serverSocketChannel =
    //              AsynchronousServerSocketChannel.open(channelGroup).bind(new
    // InetSocketAddress(8080));

    // Single-threaded version
    AsynchronousServerSocketChannel serverSocketChannel =
        AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));

    serverSocketChannel.accept(
        null,
        new CompletionHandler<AsynchronousSocketChannel, Object>() {
          @Override
          public void completed(AsynchronousSocketChannel client, Object attachment) {
            serverSocketChannel.accept(null, this);
            try {
              System.out.println(client.getRemoteAddress());
              ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
              client.read(
                  byteBuffer,
                  byteBuffer,
                  new CompletionHandler<Integer, ByteBuffer>() {
                    @Override
                    public void completed(Integer result, ByteBuffer attachment) {
                      attachment.flip();
                      byte[] content = new byte[attachment.limit()];
                      attachment.get(content);
                      System.out.println(new String(content));
                      try {
                        System.out.println("Client: " + client.getRemoteAddress());
                      } catch (IOException e) {
                        e.printStackTrace();
                      }
                    }

                    @Override
                    public void failed(Throwable exc, ByteBuffer attachment) {
                      System.out.println("failed: " + exc.getMessage());
                    }
                  });

            } catch (Exception e) {
              e.printStackTrace();
            }
          }

          @Override
          public void failed(Throwable exc, Object attachment) {}
        });

    while (true) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

AIO client code example:

public class AIOClient {

  public static void main(String[] args) throws Exception {
    AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open();
    socketChannel.connect(new InetSocketAddress("127.0.0.1", 8080));
    Thread.sleep(1000);
    ByteBuffer buffer = ByteBuffer.wrap("Hello Server".getBytes());
    socketChannel.write(buffer).get();
  }
}

Posted by XenoPhage on Wed, 28 Aug 2019 06:51:25 -0700