java异步IO之AIO示例

服务端开发

服务端启动代码如下:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值