AIO程式設計(NIO2.0)及程式碼實現
阿新 • • 發佈:2019-01-15
AIO程式設計
NIO 2.0引入了新的非同步通道的概念,並提供了非同步檔案通道和非同步套接字通道的實現。
非同步的套接字通道時真正的非同步非阻塞I/O,對應於UNIX網路程式設計中的事件驅動I/O(AIO)。他不需要過多的Selector對註冊的通道進行輪詢即可實現非同步讀寫,從而簡化了NIO的程式設計模型。
直接上程式碼吧。
3.1、Server端程式碼
Server:
print?- package com.anxpp.io.calculator.aio.server;
- /**
- * AIO服務端
- * @author yangtao__anxpp.com
- * @version 1.0
- */
- publicclass Server {
- privatestaticint DEFAULT_PORT = 12345;
- privatestatic AsyncServerHandler serverHandle;
- publicvolatilestaticlong clientCount = 0;
- publicstaticvoid start(){
- start(DEFAULT_PORT);
- }
- publicstaticsynchronizedvoid start(int port){
- if(serverHandle!=
- return;
- serverHandle = new AsyncServerHandler(port);
- new Thread(serverHandle,"Server").start();
- }
- publicstaticvoid main(String[] args){
- Server.start();
- }
- }
AsyncServerHandler:
print?- package com.anxpp.io.calculator.aio.server;
- import
- import java.net.InetSocketAddress;
- import java.nio.channels.AsynchronousServerSocketChannel;
- import java.util.concurrent.CountDownLatch;
- publicclass AsyncServerHandler implements Runnable {
- public CountDownLatch latch;
- public AsynchronousServerSocketChannel channel;
- public AsyncServerHandler(int port) {
- try {
- //建立服務端通道
- channel = AsynchronousServerSocketChannel.open();
- //繫結埠
- channel.bind(new InetSocketAddress(port));
- System.out.println("伺服器已啟動,埠號:" + port);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- @Override
- publicvoid run() {
- //CountDownLatch初始化
- //它的作用:在完成一組正在執行的操作之前,允許當前的現場一直阻塞
- //此處,讓現場在此阻塞,防止服務端執行完成後退出
- //也可以使用while(true)+sleep
- //生成環境就不需要擔心這個問題,以為服務端是不會退出的
- latch = new CountDownLatch(1);
- //用於接收客戶端的連線
- channel.accept(this,new AcceptHandler());
- try {
- latch.await();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
AcceptHandler:
print?- package com.anxpp.io.calculator.aio.server;
- import java.nio.ByteBuffer;
- import java.nio.channels.AsynchronousSocketChannel;
- import java.nio.channels.CompletionHandler;
- //作為handler接收客戶端連線
- publicclass AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AsyncServerHandler> {
- @Override
- publicvoid completed(AsynchronousSocketChannel channel,AsyncServerHandler serverHandler) {
- //繼續接受其他客戶端的請求
- Server.clientCount++;
- System.out.println("連線的客戶端數:" + Server.clientCount);
- serverHandler.channel.accept(serverHandler, this);
- //建立新的Buffer
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- //非同步讀 第三個引數為接收訊息回撥的業務Handler
- channel.read(buffer, buffer, new ReadHandler(channel));
- }
- @Override
- publicvoid failed(Throwable exc, AsyncServerHandler serverHandler) {
- exc.printStackTrace();
- serverHandler.latch.countDown();
- }
- }
ReadHandler:
print?- package com.anxpp.io.calculator.aio.server;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.nio.ByteBuffer;
- import java.nio.channels.AsynchronousSocketChannel;
- import java.nio.channels.CompletionHandler;
- import com.anxpp.io.utils.Calculator;
- publicclass ReadHandler implements CompletionHandler<Integer, ByteBuffer> {
- //用於讀取半包訊息和傳送應答
- private AsynchronousSocketChannel channel;
- public ReadHandler(AsynchronousSocketChannel channel) {
- this.channel = channel;
- }
- //讀取到訊息後的處理
- @Override
- publicvoid completed(Integer result, ByteBuffer attachment) {
- //flip操作
- attachment.flip();
- //根據
- byte[] message = newbyte[attachment.remaining()];
- attachment.get(message);
- try {
- String expression = new String(message, "UTF-8");
- System.out.println("伺服器收到訊息: " + expression);
- String calrResult = null;
- try{
- calrResult = Calculator.cal(expression).toString();
- }catch(Exception e){
- calrResult = "計算錯誤:" + e.getMessage();
- }