Java網絡編程 -- AIO異步網絡編程

AIO中的A即Asynchronous,AIO即異步IO。它是異步非阻塞的,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理,通常咱們的業務處理邏輯會變成一個回調函數,等待IO操做完成後,由系統自動觸發。vue

在進行讀寫操做時,只需直接調用API的read/write方法便可。這兩種方法均爲異步的,對於讀操做而言,當有流可讀取時,操做系統會將可讀的流傳入read方法的緩衝區,並通知應用程序;對於寫操做而言,當操做系統將write方法傳遞的流寫入完畢時,操做系統主動通知應用程序。便可以理解爲,read/write方法都是異步的,完成後會主動調用回調函數。c++

AIO實際上是對NIO的加強,新增了許多支持異步的類如AsynchronousServerSocketChannel,AsynchronousChannel,AsynchronousChannelGroup,CompletionHandler等。windows

在Linux系統中AIO和NIO的底層實現都是epoll,epoll自己是輪詢模型,AIO只不過是對epoll又包了一層,而在windows系統中AIO是經過IOCP(完成端口)實現。而目前大多數的服務器都是Linux系統,這也是Netty中使用NIO而非AIO的一個緣由,在實際使用中因爲操做系統的差別,AIO的性能有時並無NIO高效,所以AIO的使用並無很普遍。服務器

AIO服務端代碼示例:markdown

public class AIOServer {

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

    // 多線程版本
    //    ExecutorService executorService = Executors.newCachedThreadPool();
    //    AsynchronousChannelGroup channelGroup =
    //        AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);
    //      AsynchronousServerSocketChannel serverSocketChannel =
    //              AsynchronousServerSocketChannel.open(channelGroup).bind(new
    // InetSocketAddress(8080));

    // 單線程版本
    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客戶端代碼示例:多線程

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();
  }
}

相關文章
相關標籤/搜索