网络编程之AIO

AIO介绍

AIO是JDK1.7引入的,也称为NIO 2.0

NIO的同步非阻塞类似于轮询,让Selector去询问各个通道的状态。

而AIO则是通过Future实现真正的异步,让IO就绪时由系统来通知应用程序。

核心类:

  • AsyncServerSocketChannel
  • AsyncSocketChannel

当进行如下操作时,都是异步的操作
+ connect/accept
+ write
+ read

可以通过两种方案处理结果:
+ 通过返回的Future对象获取结果
+ 通过CompletionHandler接口实现回调

对于CompletionHandler接口,里面有completedfailed方法,分别代表成功后的回调和失败后的回调。

代码示例

实现一个客户端给服务端发送数据,服务端按原数据返回的程序。

服务端:

public class Server {
    final String LOCALHOST = "localhost";
    final int DEFAULT_PORT = 8888;
    AsynchronousServerSocketChannel serverSocketChannel;

    private void close(Closeable... closeable){
        for(Closeable c:closeable){
            try {
                c.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void start(){
        try {
            // 绑定监听端口
            serverSocketChannel = AsynchronousServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(LOCALHOST,DEFAULT_PORT));
            System.out.println("启动服务器,监听端口:"+DEFAULT_PORT);

            while (true) {
                serverSocketChannel.accept(null,new AcceptHandler());
                System.in.read();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(serverSocketChannel);
        }
    }
    private class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel,Object>{
        @Override
        public void completed(AsynchronousSocketChannel result, Object attachment) {
            if(serverSocketChannel.isOpen()){
                serverSocketChannel.accept(null,this);
            }

            AsynchronousSocketChannel clientChannel = result;
            if(clientChannel!=null&&clientChannel.isOpen()){
                ClientHandler handler = new ClientHandler(clientChannel);
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                Map<String,Object> info = new HashMap<>();
                info.put("type","read");
                info.put("buffer",buffer);
                clientChannel.read(buffer,info,handler);

            }
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            // 处理错误
            exc.printStackTrace();
            if(serverSocketChannel.isOpen()){
                serverSocketChannel.accept(null,this);
            }
        }
    }
    private class ClientHandler implements CompletionHandler<Integer,Object>{
        private AsynchronousSocketChannel clientChannel;
        public ClientHandler(AsynchronousSocketChannel channel){
            this.clientChannel = channel;
        }
        @Override
        public void completed(Integer result, Object attachment) {
            Map<String,Object> info = (Map<String, Object>) attachment;
            String type = (String) info.get("type");
            if(type.equals("read")){
                ByteBuffer buffer = (ByteBuffer) info.get("buffer");
                buffer.flip();
                info.put("type","write");
                clientChannel.write(buffer,info,this);
                buffer.clear();
            }else if(type.equals("write")){
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                info.put("type","read");
                info.put("buffer",buffer);
                clientChannel.read(buffer,info,this);
            }
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            //处理错误
        }
    }

    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }
}

客户端:

public class Client {
    final String LOCALHOST = "localhost";
    final int DEFAULT_PORT = 8888;
    AsynchronousSocketChannel clientSocketChannel;

    private void close(Closeable... closeable){
        for(Closeable c:closeable){
            try {
                c.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void start(){
        // 创建channel
        try {
            clientSocketChannel = AsynchronousSocketChannel.open();
            Future<Void> future = clientSocketChannel.connect(new InetSocketAddress(LOCALHOST, DEFAULT_PORT));
            future.get();
            // 等待用户的输入
            BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
            while(true){
                String input = consoleReader.readLine();
                byte[] inputBytes = input.getBytes();
                ByteBuffer buffer = ByteBuffer.wrap(inputBytes);
                Future<Integer> writeResult = clientSocketChannel.write(buffer);
                writeResult.get();
                buffer.flip();
                Future<Integer> readResult = clientSocketChannel.read(buffer);
                readResult.get();
                String echo = new String(buffer.array());
                buffer.clear();
                System.out.println(echo);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            close(clientSocketChannel);
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b%e4%b9%8baio/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年2月8日 21:47
下一篇 2020年2月9日

相关推荐

  • 深入理解java虚拟机第三版读书笔记13

    以下是第十三章 Java内存模型与线程的内容 线程安全 当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任…

    2020年1月30日
    0130
  • Java自动装箱缓存机制

    尝试运行这段代码: 相似的两段代码,得到的结果却完全不相同。 首先要知道在java中==比较的是对象的引用,从直觉出发,无论是integer1、integer2还是integer3…

    Java 2019年12月5日
    0140
  • Java多线程基础

    多线程应用 异步调用 以调用方角度来讲,如果+ 需要等待结果返回,才能继续运行就是同步+ 不需要等待结果返回,就能继续运行就是异步 同步在多线程中还有另外一个意思,是让多个线程步调…

    2020年1月31日
    0340
  • 深入理解java虚拟机第三版读书笔记09

    续深入理解java虚拟机第三版读书笔记08 类加载器 通过一个类的全限定名来获取描述该类的二进制字节流称为类加载器。类加载器可以用户自定义,是java语言流行的一项原因 类与类加载…

    2020年1月23日
    0130
  • LinkedHashMap源码分析

    总结 总结放前面防止太长不看: LinkedHashMap继承自HashMap,为Entry额外维护了两个属性:before和after,可以按照节点的插入顺序或者访问顺序为Ent…

    Java 2020年2月19日
    0550
  • 日志门面介绍和JCL使用

    日志门面概述 之前有写过Java日志框架JUL和Log4j介绍,可以对比发现它们之间的使用还是有一些区别的,比如有一些类名是不同的、日志的输出级别也不完全一致。 那么实际上是增大了…

  • JDK8u20字符串去重

    优点:节省大量内存 缺点:略微多占用cpu时间,新生代回收时间略微增加 -XX:+UseStringDeduplication String s1 = new String("he…

    Java 2020年1月15日
    0740
  • 深入理解java虚拟机第三版读书笔记07

    附: Java虚拟机规范-Java虚拟机指令集:JDK8 Java虚拟机规范-Java虚拟机指令集:JDK13 续深入理解java虚拟机第三版读书笔记06 字节码指令简介 Java…

    Java 2020年1月21日
    0230
  • 常用开源数据库连接池C3P0、Druid介绍

    概述 很多时候,连接的混乱管理所造成的系统资源开销过大成为制约大型企业级应用效率的瓶颈。因为每一次WEB请求都要建立一次数据库连接,建立连接是一个耗费资源的活动,每次都得花费0.0…

  • JUC包下的线程协作计数CountDownLatch及CyclicBarrier

    CountDownLatch 概述 用来进行线程同步协作,等待所有线程完成倒计时。 其中构造参数用来初始化等待计数值,await() 用来等待计数归零,countDown() 用来…

    Java 2020年2月6日
    01900

发表回复

登录后才能评论