AIO - 概述

简介: 介绍AIO使用,以及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");


 

 

相关文章
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
1690 0
|
运维 监控 网络协议
什么是运营商级 NAT (CGNAT)?
【4月更文挑战第16天】
8676 10
什么是运营商级 NAT (CGNAT)?
|
安全 Linux Nacos
解决“nacos默认secret.key配置不当权限绕过漏洞“
解决“nacos默认secret.key配置不当权限绕过漏洞“
3499 0
|
6月前
|
Web App开发 人工智能 安全
LINE 多开怎么实现?五种方案一次讲清!(含个人号与官方号)
跨境业务工具太分散?这篇文章教你用 OpenClaw 串联引流、客服、数据分析与自动化,通过 4个 OpenClaw Skill 搭建完整的跨境业务闭环。
1175 2
|
7月前
|
Java 容器 JavaScript
从"代码跑不通"到"答辩演示丝滑流畅":毕设部署避坑完全指南
毕设答辩“最后一公里”常因部署失败翻车!本文提供本地一键、云服务器、Docker三种部署方案,重点推荐智码方舟AI生成器——10分钟获取配置完备的部署文档+脚本,规避90%环境问题,助你稳过答辩。
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
1265 2
|
7月前
|
传感器 人工智能 边缘计算
数字孪生项目的开发
数字孪生项目是构建物理实体实时映射、动态演化的高集成数字闭环系统。涵盖五大阶段:资产建模(UE5/Unity+LOD优化)、数据底座(IoT+GIS/BIM+机理/AI模型)、实时渲染(数据映射+像素流送)、交互控制(反向操控+告警溯源)及部署迭代。支持BIM对接或全栈外包。
|
7月前
|
机器学习/深度学习 算法 安全
基于强化学习Q-learning算法的无人机三维路径规划算法原理与实现附MATLAB代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 👇 关注我领取海量matlab电子书和数学建模资料 🍊个人信条:格物致知,完整Matlab代码获取及仿真咨询内容私信。 🔥 内容介绍 一、无人机三维路径规划的复杂性与挑战 环境复杂性:无人机在三维空间中飞行,面临的环境极为复杂。不仅存在如建筑物、山脉、高压线等静态障碍物,还有其他飞行器等动态障碍物。这些障碍物的分布使得无人机可飞行的空间被严重限制,要在其中找到一条安全的路径极具挑战性。例如
266 0
|
9月前
|
开发框架 弹性计算 运维
建站系统哪个好?2025年建站系统深度推荐与避坑指南
建站系统分传统CMS(如PageAdmin)、SaaS平台(如阿里云速成美站)和开发框架三类。选择时需权衡控制权、成本与效率,根据业务需求、技术能力和长期规划理性选型,优先验证可行性再迭代升级。
1100 0
|
SQL Java 数据库连接
深入解析@MapperScan注解:简化MyBatis接口与映射器的关联
在Java持久化领域,MyBatis是一个广泛使用的ORM(对象关系映射)框架,用于将数据库中的数据映射到Java对象中。MyBatis的核心概念是SQL映射器(Mapper),它定义了数据库操作的方法。为了简化Mapper接口与映射器的关联,MyBatis提供了`@MapperScan`注解。本文将深入探讨`@MapperScan`注解的作用、用法,以及在MyBatis应用中的应用场景。
3674 0