java异步IO之AIO示例

java异步IO之AIO示例

  • 服务端开发
    • 服务端启动代码如下:
    • 服务端业务处理逻辑示例代码TimeHandler
    • 回调处理类 ReadCompletionHandler
  • 客户端代码
  • 原理

服务端开发

服务端启动代码如下:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.TimeUnit;

public class TimeServer {

    private int port;
    private AsynchronousServerSocketChannel socketChannel;

    public AsynchronousServerSocketChannel getSocketChannel() {
        return socketChannel;
    }

    public static void main(String[] args) throws InterruptedException {
        new TimeServer(8090);
        //模拟主线程等待
        TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
    }

    public TimeServer(int port){
        this.port = port;
        try {
            init(port);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private void init(int port) throws IOException {
        //打开异步socket服务端
        socketChannel = AsynchronousServerSocketChannel.open();
        //板顶监听端口,设置最大连接数
        socketChannel.bind(new InetSocketAddress(port),1024);
        //这里绑定TimeHandler ,当有新的客户端接入成功后会回调TimeHandler的completed
        // 在这个completed方法中要继续调用accept方法,继续接收其它请求,this就是TimeServer本身
        socketChannel.accept(this,new TimeHandler());
        System.out.println("server start");
    }
}

服务端业务处理逻辑示例代码TimeHandler

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class TimeHandler implements CompletionHandler<AsynchronousSocketChannel,TimeServer> {


    @Override
    public void completed(AsynchronousSocketChannel result, TimeServer attachment) {
        // 在这个completed方法中要继续调用accept方法,继续接收其它请求,形成类似链式调用
        attachment.getSocketChannel().accept(attachment,this);
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        //调用异步读取的方法,参数一:接收缓冲区 参数二:附件参数 参数三:回调处理类
        //当读取完成客户端发送过来的信息,回调ReadCompletionHandler的方法
        result.read(byteBuffer,byteBuffer,new ReadCompletionHandler(result));
    }

    @Override
    public void failed(Throwable exc, TimeServer attachment) {
        exc.printStackTrace();
        System.out.println("failed");
    }
}

回调处理类 ReadCompletionHandler

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {

    private AsynchronousSocketChannel channel;

    public ReadCompletionHandler(AsynchronousSocketChannel channel) {
        this.channel = channel;
    }

    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        try {
        	//获取并打印客户端发送过来的消息
            attachment.flip();
            byte[] bytes = new byte[attachment.remaining()];
            attachment.get(bytes);
            String msg = new String(bytes, "utf-8");
            System.out.println("get msg from client:"+msg);
            //服务端响应客户端写回消息
            doWrite(System.currentTimeMillis()+"server send msg");
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private void doWrite(String str) {
        byte[] bytes = str.getBytes();
        ByteBuffer writeBuff = ByteBuffer.allocate(bytes.length);
        writeBuff.put(bytes);
        writeBuff.flip();
        //将消息写到缓冲区进行发送,写完成后回调方法
        channel.write(writeBuff,writeBuff,new CompletionHandler<Integer, ByteBuffer>(){
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                //没有发送完成,接续发送
                if (attachment.hasRemaining()){
                    channel.write(attachment,attachment,this);
                }
            }

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

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

    private void close(){
        try {
            if (channel != null)
                channel.close();
        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

客户端代码

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.TimeUnit;

public class AsyncTimerClient implements CompletionHandler<Void, AsyncTimerClient> {

    private String host;
    private int port;
    private AsynchronousSocketChannel client;

    public AsyncTimerClient(String host, int port) {
        this.host = host;
        this.port = port;
        try {
            //开启异步socket通道
            client = AsynchronousSocketChannel.open();
            //参数二:附件   参数三:处理器,实现CompletionHandler接口
            client.connect(new InetSocketAddress(host,port),this,this);
            System.out.println("client start");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //当一个操作完成时进行回调,比如连接建立,收到消息等
    @Override
    public void completed(Void result, AsyncTimerClient attachment) {
        byte[] bytes = "send time to server".getBytes();
        ByteBuffer WriteBuffer = ByteBuffer.allocate(bytes.length);
        WriteBuffer.put(bytes);
        WriteBuffer.flip();
        client.write(WriteBuffer, WriteBuffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                //判断没有写完,继续写
                if (attachment.hasRemaining()){
                    client.write(attachment,attachment,this);
                }else {
                	//读取客户端返回的消息
                    ByteBuffer readBuff = ByteBuffer.allocate(1024);
                    client.read(readBuff, readBuff, new CompletionHandler<Integer, ByteBuffer>() {
                        @Override
                        public void completed(Integer result, ByteBuffer attachment) {
                            attachment.flip();
                            byte[] readByte = new byte[attachment.remaining()];
                            attachment.get(readByte);
                            String msg = null;
                            try {
                                msg = new String(readByte, "UTF-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                            System.out.println(" msg from server:"+msg);
                        }

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

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

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

    private void close(){
        try {
            if (client != null)
                client.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws InterruptedException {
        new AsyncTimerClient("127.0.0.1",8090);
        TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
    }
}

原理

JDK底层通过线程池ThreadPoolExecutor来执行aio的异步回调,最终回调通知类由 AsynchronousChannelGroupImpl实现。

JAVA AIO框架在windows下使用windows IOCP技术,在Linux下使用epoll多路复用IO技术模拟异步IO

你可能感兴趣的:(NIO和Netty)