java核心學習(三十三) 網絡編程---AIO實現異步Socket通信


  AIO需要操作系統的支持,在linux內核2.6版本中加入了對真正異步IO的支持,java從jdk1.7開始支持AIO

核心類有AsynchronousSocketChannel 、AsynchronousServerSocketChannel、AsynchronousChannelGroup

  前兩個個類是javaAIO為TCP通信提供的異步Channel。看名字就知道應該是干什么的了。

  創建AsynchronousServerSocketChannel的代碼如下:    

AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(PORT));

  其中open()有一個重載方法,可以使用指定的AsynchronousChannelGroup來創建AsynchronousServerSocketChannel。

  AsynchronousChannelGroup是異步Channel的分組管理器,它可以實現資源共享。創建AsynchronousChannelGroup時,需要傳入一個ExecutorService,也就是綁定一個線程池,該線程池負責兩個任務:處理IO事件和觸發CompletionHandler回調接口。代碼如下:

  

AsynchronousServerSocketChannel serverSocketChannel = null;
        try {
            ExecutorService executorService = Executors.newFixedThreadPool(80);
            AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup.withThreadPool(executorService);
            serverSocketChannel = AsynchronousServerSocketChannel.open(channelGroup).bind(new InetSocketAddress(9000));
        }catch (IOException ioe){
            ioe.printStackTrace();
        }

    AsynchronousServerSocketChannel創建成功后,類似於ServerSocket,也是調用accept()方法來接受來自客戶端的連接,由於異步IO實際的IO操作是交給操作系統來做的,用戶進程只負責通知操作系統進行IO和接受操作系統IO完成的通知。所以異步的ServerChannel調用accept()方法后,當前線程不會阻塞,程序也不知道accept()方法什么時候能夠接收到客戶端請求並且操作系統完成網絡IO,為解決這個問題,AIO為accept方法提供兩個版本:

    Future<AsynchronousSocketChannel> accept() :開始接收客戶端請求,如果當前線程需要進行網絡IO(即獲得AsynchronousSocketChannel),則應該調用該方法返回的Future對象的get()方法,但是get方法會阻塞該線程,所以這種方式是阻塞式的異步IO。

    <A> void accept(A attachment ,CompletionHandler<AsynchronousSocketChannel,? super A> handler):開始接受來自客戶端請求,連接成功或失敗都會觸發CompletionHandler對象的相應方法。其中AsynchronousSocketChannel就代表該CompletionHandler處理器在處理連接成功時的result是AsynchronousSocketChannel的實例。

    而CompletionHandler接口中定義了兩個方法,

      completed(V result , A attachment):當IO完成時觸發該方法,該方法的第一個參數代表IO操作返回的對象,第二個參數代表發起IO操作時傳入的附加參數。

      faild(Throwable exc, A attachment):當IO失敗時觸發該方法,第一個參數代表IO操作失敗引發的異常或錯誤。

    使用第一種accept方法需要如下代碼

    

while (true){
            Future<AsynchronousSocketChannel> future = serverSocketChannel.accept();
            AsynchronousSocketChannel socketChannel = null;
            try {
                socketChannel = future.get();
                socketChannel.write(ByteBuffer.wrap("ssss".getBytes("UTF-8")));
            }catch (Exception e){
                e.printStackTrace();
            }


        }

    通常使用第二種accept,實現自己的CompletionHandler實現類。

 

    而AsynchronousSocketChannel的的用法與Socket類似,由三個方法,但是不同的是每個方法又分為Future版本與CompletionHandler版本。

      connect():用於連接到指定端口,指定IP地址的服務器

      read()、write():完成讀寫。

    注意!使用異步Channel時,accept()、connect()、read()、write()等方法都不會阻塞,也就是說如果使用返回Future的這些方法,程序並不能直到什么時候成功IO,必須要使用get方法,等get方法的阻塞結束后才能確保IO完成,繼續執行下面的操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM