1. 程式人生 > >AIO程式設計(NIO2.0)及程式碼實現

AIO程式設計(NIO2.0)及程式碼實現

AIO程式設計

    NIO 2.0引入了新的非同步通道的概念,並提供了非同步檔案通道和非同步套接字通道的實現。

    非同步的套接字通道時真正的非同步非阻塞I/O,對應於UNIX網路程式設計中的事件驅動I/O(AIO)。他不需要過多的Selector對註冊的通道進行輪詢即可實現非同步讀寫,從而簡化了NIO的程式設計模型。

    直接上程式碼吧。

    3.1、Server端程式碼

    Server:

 print?
  1. package com.anxpp.io.calculator.aio.server;  
  2. /** 
  3.  * AIO服務端 
  4.  * @author yangtao__anxpp.com 
  5.  * @version 1.0
     
  6.  */
  7. publicclass Server {  
  8.     privatestaticint DEFAULT_PORT = 12345;  
  9.     privatestatic AsyncServerHandler serverHandle;  
  10.     publicvolatilestaticlong clientCount = 0;  
  11.     publicstaticvoid start(){  
  12.         start(DEFAULT_PORT);  
  13.     }  
  14.     publicstaticsynchronizedvoid start(int port){  
  15.         if(serverHandle!=
    null)  
  16.             return;  
  17.         serverHandle = new AsyncServerHandler(port);  
  18.         new Thread(serverHandle,"Server").start();  
  19.     }  
  20.     publicstaticvoid main(String[] args){  
  21.         Server.start();  
  22.     }  
  23. }  

    AsyncServerHandler:

 print?
  1. package com.anxpp.io.calculator.aio.server;  
  2. import
     java.io.IOException;  
  3. import java.net.InetSocketAddress;  
  4. import java.nio.channels.AsynchronousServerSocketChannel;  
  5. import java.util.concurrent.CountDownLatch;  
  6. publicclass AsyncServerHandler implements Runnable {  
  7.     public CountDownLatch latch;  
  8.     public AsynchronousServerSocketChannel channel;  
  9.     public AsyncServerHandler(int port) {  
  10.         try {  
  11.             //建立服務端通道
  12.             channel = AsynchronousServerSocketChannel.open();  
  13.             //繫結埠
  14.             channel.bind(new InetSocketAddress(port));  
  15.             System.out.println("伺服器已啟動,埠號:" + port);  
  16.         } catch (IOException e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.     @Override
  21.     publicvoid run() {  
  22.         //CountDownLatch初始化
  23.         //它的作用:在完成一組正在執行的操作之前,允許當前的現場一直阻塞
  24.         //此處,讓現場在此阻塞,防止服務端執行完成後退出
  25.         //也可以使用while(true)+sleep 
  26.         //生成環境就不需要擔心這個問題,以為服務端是不會退出的
  27.         latch = new CountDownLatch(1);  
  28.         //用於接收客戶端的連線
  29.         channel.accept(this,new AcceptHandler());  
  30.         try {  
  31.             latch.await();  
  32.         } catch (InterruptedException e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.     }  
  36. }  

    AcceptHandler:

 print?
  1. package com.anxpp.io.calculator.aio.server;  
  2. import java.nio.ByteBuffer;  
  3. import java.nio.channels.AsynchronousSocketChannel;  
  4. import java.nio.channels.CompletionHandler;  
  5. //作為handler接收客戶端連線
  6. publicclass AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AsyncServerHandler> {  
  7.     @Override
  8.     publicvoid completed(AsynchronousSocketChannel channel,AsyncServerHandler serverHandler) {  
  9.         //繼續接受其他客戶端的請求
  10.         Server.clientCount++;  
  11.         System.out.println("連線的客戶端數:" + Server.clientCount);  
  12.         serverHandler.channel.accept(serverHandler, this);  
  13.         //建立新的Buffer
  14.         ByteBuffer buffer = ByteBuffer.allocate(1024);  
  15.         //非同步讀  第三個引數為接收訊息回撥的業務Handler
  16.         channel.read(buffer, buffer, new ReadHandler(channel));  
  17.     }  
  18.     @Override
  19.     publicvoid failed(Throwable exc, AsyncServerHandler serverHandler) {  
  20.         exc.printStackTrace();  
  21.         serverHandler.latch.countDown();  
  22.     }  
  23. }  

    ReadHandler:

 print?
  1. package com.anxpp.io.calculator.aio.server;  
  2. import java.io.IOException;  
  3. import java.io.UnsupportedEncodingException;  
  4. import java.nio.ByteBuffer;  
  5. import java.nio.channels.AsynchronousSocketChannel;  
  6. import java.nio.channels.CompletionHandler;  
  7. import com.anxpp.io.utils.Calculator;  
  8. publicclass ReadHandler implements CompletionHandler<Integer, ByteBuffer> {  
  9.     //用於讀取半包訊息和傳送應答
  10.     private AsynchronousSocketChannel channel;  
  11.     public ReadHandler(AsynchronousSocketChannel channel) {  
  12.             this.channel = channel;  
  13.     }  
  14.     //讀取到訊息後的處理
  15.     @Override
  16.     publicvoid completed(Integer result, ByteBuffer attachment) {  
  17.         //flip操作
  18.         attachment.flip();  
  19.         //根據
  20.         byte[] message = newbyte[attachment.remaining()];  
  21.         attachment.get(message);  
  22.         try {  
  23.             String expression = new String(message, "UTF-8");  
  24.             System.out.println("伺服器收到訊息: " + expression);  
  25.             String calrResult = null;  
  26.             try{  
  27.                 calrResult = Calculator.cal(expression).toString();  
  28.             }catch(Exception e){  
  29.                 calrResult = "計算錯誤:" + e.getMessage();  
  30.             }  
  31.