当前位置: 首页 > news >正文

AIO - 概述


本博客是《Netty威指南》的读书,如有错误环境指正、探谢谢!此码见附件。

此博客涉及的代码地址https://gitee.com/wuzhengfei/great-truth;参考com.wzf.greattruth.aio包中的代

IO模型参考:https://yq.aliyun.com/articles/277102


JDK1.7升级了NIO类库,升级后的NIO类库被称为NIO2.0,此版本正式提供了异步IO操作,即AIO。

 

1. AIO服务端序列

adcc8021b13070ba6bf4b76f5c30d3821ed03f05

 

2. AIO服务端序列分析

1)打开AsynchronousServerSocketChannel

asynServerSocketChannel = AsynchronousServerSocketChannel.open();

 

2) 绑定监听地址InetSocketAddress

asynServerSocketChannel.bind(new InetSocketAddress(port));

 

3) 创建线程并启动

AsyncServerHandler timeServer = new AsyncServerHandler(port);

new Thread(timeServer, "AIOServerHandler").start();

 

4)注册接收数据的Handler

asynServerSocketChannel.accept(this, new ServerAcceptCompletionHandler());

 

5)接收数据,实现ServerAcceptCompletionHandler的completed、failed方法


public void completed(AsynchronousSocketChannel channel, AsyncServerHandler attachment) {

    /**

    * 为什么需要再次调用accept方法?

    * 因为如果有新的客户端连接接入,系统将回调我们传入的CompletionHandler示例的complete方法,表示新的客户端接入成功

    * 因为一个AsynchronousServerSocketChannel可以接收成千上万个客户端,所以需要继续调用他的accept方法,

    * 接收其他客户端连接,最终形成一个循环。每当接收一个客户连接成功后,再异步接收新的客户端连接

    * 

    */

        attachment.asynServerSocketChannel.accept(attachment, this);

    ByteBuffer buffer = ByteBuffer.allocate(1024);

    /**

    * ByteBuffer:接收缓冲区,用于从异步的Channel中读取数据包

    * Attachment:异步Channel携带的附件,通知回调的时候作为入参使用

    * CompletionHandler:接收通知回调的业务Handler

    */

    channel.read(buffer, buffer, new ServerReadCompletionHandler(channel));

    }

 

public void failed(Throwable exc, AsyncServerHandler attachment) {

    exc.printStackTrace();

    attachment.latch.countDown();

}


 

6)读取数据,实现ServerReadCompletionHandler的Complete、faild方法

public void completed(Integer result, ByteBuffer attachment) {

    // handler with data

}

public void failed(Throwable exc, ByteBuffer attachment) {

    this.channel.close();

}


 

7)decode数据 

attachment.flip();

byte[] body = new byte[attachment.remaining()];

attachment.get(body);

String req = new String(body, "UTF-8");

 

8)异步写数据到Channel

byte[] bytes = (response).getBytes();

ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);

writeBuffer.put(bytes);

writeBuffer.flip();

channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {

    @Override

    public void completed(Integer result, ByteBuffer buffer) {

        // 如果没有发送完成,继续发送

        if (buffer.hasRemaining())

             channel.write(buffer, buffer, this);

    }

 

    @Override

    public void failed(Throwable exc, ByteBuffer attachment) {

        try {

             channel.close();

        } catch (IOException e) {

             // ingnore on close

        }

    }

});


3.AIO客户端序列

dbd127f098f47e5827f1d4b16833ace278700fe9

 

4. AIO客户端序列分析

1)打开AsynchronousSocketChannel

asynSocketChannel = AsynchronousSocketChannel.open();

 

2)异步连接服务器

asynSocketChannel.connect(new InetSocketAddress(host, port), this, this);

3)创建线程并启动 


AsyncClientHandler asyncClientHandler = new AsyncClientHandler("127.0.0.1", port);

new Thread(asyncClientHandler, "AIOClientHandler").start();

 

4)注册连接Server成功的Handler

ClientConnectCompletionHandler connectCompletionHandler = new ClientConnectCompletionHandler(asynSocketChannel, latch) ;

asynSocketChannel.connect(new InetSocketAddress(host, port), connectCompletionHandler, connectCompletionHandler);

 

5)连接成功后,注册向Server写数据的Handler,实现Completed、Failed方法

public void completed(Void result, AsyncClientHandler attachment) {

    byte[] req = "timestemp".getBytes();

    ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);

    writeBuffer.put(req);

    writeBuffer.flip();

 

    ClientWriteCompletionHandler writeCompletionHandler = new ClientWriteCompletionHandler(

             attachment.asynSocketChannel, attachment.latch);

    attachment.asynSocketChannel.write(writeBuffer, writeBuffer, writeCompletionHandler);

}

 

@Override

public void failed(Throwable exc, AsyncClientHandler attachment) {

    exc.printStackTrace();

    try {

        attachment.asynSocketChannel.close();

        attachment.latch.countDown();

    } catch (IOException e) {

        e.printStackTrace();

    }

}


 

 

6)向Server发送数据,实现CompletionHandler的Completed、faild方法


public void completed(Integer result, ByteBuffer buffer) {

    if (buffer.hasRemaining()) {

        asynSocketChannel.write(buffer, buffer, this);

    }

}

 

public void failed(Throwable exc, ByteBuffer attachment) {

    try {

        asynSocketChannel.close();

        latch.countDown();

    } catch (IOException e) {

        // ingnore on close

    }

}


 

7)注册读数据的Handler,实现completed、failed方法

asynSocketChannel.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {

    @Override

    public void completed(Integer result, ByteBuffer buffer) {

        buffer.flip();

        byte[] bytes = new byte[buffer.remaining()];

        buffer.get(bytes);

        String body;

        try {

             body = new String(bytes, "UTF-8");

             System.out.println("Now is : " + body);

             latch.countDown();

        } catch (UnsupportedEncodingException e) {

             e.printStackTrace();

        }

    }

 

    @Override

    public void failed(Throwable exc, ByteBuffer attachment) {

        try {

             asynSocketChannel.close();

             latch.countDown();

        } catch (IOException e) {

             // ingnore on close

        }

    }

});

 

8)读取并decode数据


buffer.flip();

byte[] bytes = new byte[buffer.remaining()];

buffer.get(bytes);

String body = new String(bytes, "UTF-8");


 

 

相关文章:

  • Azure Redis Cache (5) Redis Cache Cluster集群模式
  • 白盒测试
  • SQL Server 2008 部分改变
  • Python将被加入高考科目
  • [转]使用WinINet和WinHTTP
  • Microsoft Ribbon for WPF 正式发布
  • 【原创】简单的局域网内无线文件传输(1)
  • 给初学者:JavaScript 中数组操作注意点
  • 阿里研究院崔瀚文:“单身经济”背后的“新家园”
  • 在Hyper-V下Linux不能使用鼠标
  • 005——VUE中的v-text与v-html的使用
  • 控制反转IOC与依赖注入DI
  • 开源免费接口管理平台 eoLinker V3.1.7发布+开源版部署指南一份
  • Android ListView A~Z快速索引(改进版)
  • AFNetworking 源码阅读
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • ES6核心特性
  • Git 使用集
  • Rancher如何对接Ceph-RBD块存储
  • Redis在Web项目中的应用与实践
  • vagrant 添加本地 box 安装 laravel homestead
  • 初识MongoDB分片
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 将回调地狱按在地上摩擦的Promise
  • 京东美团研发面经
  • 实战|智能家居行业移动应用性能分析
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 小程序测试方案初探
  • 一个JAVA程序员成长之路分享
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • C# - 为值类型重定义相等性
  • 阿里云ACE认证学习知识点梳理
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • #FPGA(基础知识)
  • (done) 两个矩阵 “相似” 是什么意思?
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (七)理解angular中的module和injector,即依赖注入
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (转)Oracle 9i 数据库设计指引全集(1)
  • *p++,*(p++),*++p,(*p)++区别?
  • 、写入Shellcode到注册表上线
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET 使用 XPath 来读写 XML 文件
  • .Net8 Blazor 尝鲜
  • @GetMapping和@RequestMapping的区别
  • @Transaction注解失效的几种场景(附有示例代码)
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [Android]使用Android打包Unity工程
  • [C++] 默认构造函数、参数化构造函数、拷贝构造函数、移动构造函数及其使用案例
  • [emuch.net]MatrixComputations(7-12)
  • [flume$2]记录一个写自定义Flume拦截器遇到的错误