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

NIO简单介绍和运用

  • NIO简单介
    NIO 非阻塞IO模型,基于缓冲区(Buffer)读写数据,读写后的数据通过通道(Channel)进行传输,采用选择器(Selector)管理多个通道从而实现高并发。
    核心组件:1. Buffer 为一个内存数组作为数据容器,代替传统的InputStream和OutputStream;2. Channel 双向数据传输;3. Selector 监听多通道区别于传统的单线程管理多连接
  • 传统的IO模型
    阻塞、非阻塞、多路复用、信号驱动、异步IO
  • 简单的NIO服务器接收客户端TCP请求
 public void start(int port) throws IOException {//创建一个选择器管理通道Selector selector = Selector.open();//创建通道并注册到选择器(可创建多个通道)createChannel(selector, port);while (true) {//阻塞,等到有事件发生时继续执行selector.select();//处理事件Iterator<SelectionKey> keys = selector.selectedKeys().iterator();while (keys.hasNext()) {SelectionKey key = keys.next();keys.remove();//新连接到达if (key.isAcceptable()) {ServerSocketChannel socketChannel = (ServerSocketChannel) key.channel();SocketChannel channel = socketChannel.accept();channel.configureBlocking(false);//注册新的读取事件channel.register(selector, SelectionKey.OP_READ);continue;}//可读取数据if (key.isReadable()) {SocketChannel channel = (SocketChannel) key.channel();//定义读取数据的缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);//读取数据到缓冲int bytes = channel.read(buffer);//客户端关闭连接if (bytes == -1) {channel.close();continue;}//切换为读取模式buffer.flip();String message = new String(buffer.array(), 0, bytes);System.out.println("接收到消息");//回显消息给客户端channel.write(ByteBuffer.wrap(message.getBytes()));}}}}
private void createChannel(Selector selector, int port) throws IOException {//创建通道并绑定端口ServerSocketChannel socketChannel = ServerSocketChannel.open();socketChannel.bind(new InetSocketAddress(port));//设置为非阻塞socketChannel.configureBlocking(false);//将通道注册到选择器socketChannel.register(selector, SelectionKey.OP_ACCEPT);}
  • Netty基于NIO的异步事件驱动的网络应用框架
    特性:异步和事件驱动、高性能(高效的线程模型和缓冲区机制)、易使用和灵活可扩展
    涉及到 channel 、callback(事件发生时的回调)、Future和Promise(异步计算)、EventLoop(事件循环)、Pipeline和ChannelHandler管道和处理器、bootstrap引导类
 public static void start(int port) {// 创建两个EventLoopGroup事件循环组,一个用于接收客户端连接,一个用于处理客户端数据EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {start(bossGroup, workerGroup, port);} catch (Exception e) {log.warn("Netty服务【{}】发生异常", port, e);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
private static void start(EventLoopGroup bossGroup, EventLoopGroup workerGroup, int port) throws InterruptedException {//创建服务器启动对象ServerBootstrap serverBootstrap = new ServerBootstrap();//parentGroup:这个事件组用于接收客户端的连接请求。它会创建一个ServerChannel,用于监听并接收客户端的连接。一旦有连接请求到达,parentGroup就会将连接分配给childGroup中的一个EventLoop来处理。//childGroup:这个事件组用于处理接收到的连接的数据。它会创建一个或多个Channel,用于与客户端进行通信。每个Channel都有一个关联的EventLoop,用于处理该Channel的I/O操作。childGroup会负责管理这些Channel和EventLoop,包括事件循环、线程分配、I/O操作等。//通过使用两个不同的事件组,可以实现多线程处理客户端连接和数据的模型。parentGroup负责接收连接请求并将其分配给childGroup处理,childGroup负责处理具体的连接和数据操作,从而提高服务器的并发性能。serverBootstrap.group(bossGroup, workerGroup)//.option(ChannelOption)可设置其它各种参数//服务器通道实现采用NioServerSocketChannel.channel(NioServerSocketChannel.class)//针对服务端的所有连接(不论已连接或是创建连接).handler(new LoggingHandler())//针对已接收到的连接的处理器配置.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) {//添加自定义解码器,如继承ByteToMessageCodec用于处理各种业务逻辑,解码器按添加的先后顺寻执行//ByteToMessageCodec主要用于解码字节数据,将其转换为消息对象,常用于解决粘包和拆包问题//ChannelInboundHandlerAdapter主要用于处理各种事件,如接收到数据、连接建立、异常处理等,同时为响应请求数据可以用用channel的writeAndFlush将数据写入并刷新网路socketChannel.pipeline().addLast(new IotDataDecoder(), new IotBusinessDecoder());}});//以下两行代码用于确保服务器在绑定端口后一直保持运行状态,直到接收到关闭信号//绑定服务器端口并启动服务 sync()使当前线程阻塞直到绑定服务器,绑定多个端口直接重复以下两行代码ChannelFuture channelFuture = serverBootstrap.bind(port).sync();//等待服务器关闭channelFuture.channel().closeFuture().sync();}
  • 通过NIO将数据流写入到本地文件
 private void write(InputStream stream, String targetPath) throws IOException {//创建通道FileChannel outChannel = FileChannel.open(Paths.get(targetPath), StandardOpenOption.CREATE, StandardOpenOption.WRITE);ReadableByteChannel inChannel = Channels.newChannel(stream);//创建缓冲区ByteBuffer buffer = ByteBuffer.allocate(2048);//写入和读取while (inChannel.read(buffer) != -1) {//调整缓冲区的位置以便读取,将位置调整到0buffer.flip();outChannel.write(buffer);//将缓冲区未读取的位置移动到起始位置buffer.compact();}buffer.flip();//判断是否有剩余内容while (buffer.hasRemaining()) {outChannel.write(buffer);}}
http://www.dtcms.com/a/286312.html

相关文章:

  • MySQL计数函数count原理分析
  • 深入理解Linux文件I/O:系统调用与标志位应用
  • 区块链加密技术全景解析
  • 高效VLP蛋白表达|病毒样颗粒生产|疫苗研发平台
  • 【无标题】标准模型粒子行为与11维拓扑量子色动力学模型严格对应的全面论述
  • 文献分享0719
  • MyBatis:配置文件完成增删改查_添加
  • 智慧后厨检测算法构建智能厨房防护网
  • 零基础入门:用按键精灵实现视频自动操作(附完整脚本)
  • C语言:数组
  • MySQL的关键日志
  • 洛谷 P1395 会议
  • Logback 配置的利器:深入理解<property>与<variable>
  • 教育行业网络升级最佳实践:SD-WAN、传统方案与混合方案对比分析
  • Android sdk 升级 34到35
  • SpringBoot中解决SpringApplication入口和其他Bean不在同属目录下的问题。
  • 暑期自学嵌入式——Day05补充(C语言阶段)
  • STM32+w5500+TcpClient学习笔记
  • 前端基础之《Vue(23)—跨域问题》
  • Effective Modern C++ 条款14:如果函数不抛出异常请使用noexcept
  • 如何将本地Git仓库推送到远程仓库的一个文件中并保留Commit记录
  • 对于编码电机-520直流减速电机
  • 硬核电子工程:从硅片到系统的全栈实战指南—— 融合电路理论、嵌入式开发与PCB设计的工程艺术
  • 正则表达式完全指南:从入门到实战
  • Web3加密货币交易:您需要知道的所有信息
  • 五分钟掌握 TDengine 数据文件的工作原理
  • 《设计模式之禅》笔记摘录 - 8.命令模式
  • 【Mediatek】AN7563搭建编译环境操作说明
  • 1 初识C++
  • 【java 安全】 IO流