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

netty之基础aio,bio,nio

前言


在Java中,提供了一些关于使用IO的API,可以供开发者来读写外部数据和文件,我们称这些API为Java IO。IO是Java中比较重要知识点,且比较难学习的知识点。并且随着Java的发展为提供更好的数据传输性能,目前有三种IO共存;分别是BIO、NIO和AIO。
在这里插入图片描述
同步阻塞I/O模式
是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。
同步非阻塞模式
NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
异步非阻塞I/O模型
是一种非阻塞异步的通信模式。在NIO的基础上引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。

aio


目录结构如下图
在这里插入图片描述

新建客服端启动类 AioClient

public class AioClient {public static void main(String[] args) throws Exception {AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open();Future<Void> future = socketChannel.connect(new InetSocketAddress("192.168.108.89", 7397));System.out.println("com.lm.netty01.aio client start done. {码农明哥 | 欢迎关注&获取源码}");future.get();socketChannel.read(ByteBuffer.allocate(1024), null, new AioClientHandler(socketChannel, Charset.forName("GBK")));Thread.sleep(100000);}}

客户端消息处理器类

public class AioClientHandler extends ChannelAdapter {public AioClientHandler(AsynchronousSocketChannel channel, Charset charset) {super(channel, charset);}@Overridepublic void channelActive(ChannelHandler ctx) {try {System.out.println("程序员码农 | 链接报告信息:" + ctx.channel().getRemoteAddress());//通知客户端链接建立成功} catch (IOException e) {e.printStackTrace();}}@Overridepublic void channelInactive(ChannelHandler ctx) {}@Overridepublic void channelRead(ChannelHandler ctx, Object msg) {System.out.println("码农明哥 | 服务端收到:" + new Date() + " " + msg + "\r\n");ctx.writeAndFlush("客户端信息处理Success!\r\n");}
}

服务端

public class AioServer extends Thread {private AsynchronousServerSocketChannel serverSocketChannel;@Overridepublic void run() {try {serverSocketChannel = AsynchronousServerSocketChannel.open(AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 10));serverSocketChannel.bind(new InetSocketAddress(7397));System.out.println("com.lm.netty01 aio server start done.  欢迎关注&获取源码}");// 等待CountDownLatch latch = new CountDownLatch(1);serverSocketChannel.accept(this, new AioServerChannelInitializer());latch.await();} catch (Exception e) {e.printStackTrace();}}public AsynchronousServerSocketChannel serverSocketChannel() {return serverSocketChannel;}public static void main(String[] args) {new AioServer().start();}
}

初始化

public class AioServerChannelInitializer extends ChannelInitializer {@Overrideprotected void initChannel(AsynchronousSocketChannel channel) throws Exception {channel.read(ByteBuffer.allocate(1024), 10, TimeUnit.SECONDS, null, new AioServerHandler(channel, Charset.forName("GBK")));}
}

处理消息

public class AioServerHandler extends ChannelAdapter {public AioServerHandler(AsynchronousSocketChannel channel, Charset charset) {super(channel, charset);}@Overridepublic void channelActive(ChannelHandler ctx) {try {System.out.println("码农明哥| 链接报告信息:" + ctx.channel().getRemoteAddress());//通知客户端链接建立成功ctx.writeAndFlush("码农明哥 | 通知服务端链接建立成功" + " " + new Date() + " " + ctx.channel().getRemoteAddress() + "\r\n");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void channelInactive(ChannelHandler ctx) {}@Overridepublic void channelRead(ChannelHandler ctx, Object msg) {System.out.println("码农明哥 | 服务端收到:" + new Date() + " " + msg + "\r\n");ctx.writeAndFlush("服务端信息处理Success!\r\n");}
}

Channle适配器模仿Netty

public abstract class ChannelAdapter implements CompletionHandler<Integer, Object> {private AsynchronousSocketChannel channel;private Charset charset;public ChannelAdapter(AsynchronousSocketChannel channel, Charset charset) {this.channel = channel;this.charset = charset;if (channel.isOpen()) {channelActive(new ChannelHandler(channel, charset));}}@Overridepublic void completed(Integer result, Object attachment) {try {final ByteBuffer buffer = ByteBuffer.allocate(1024);final long timeout = 60 * 60L;channel.read(buffer, timeout, TimeUnit.SECONDS, null, new CompletionHandler<Integer, Object>() {@Overridepublic void completed(Integer result, Object attachment) {if (result == -1) {try {channelInactive(new ChannelHandler(channel, charset));channel.close();} catch (IOException e) {e.printStackTrace();}return;}buffer.flip();channelRead(new ChannelHandler(channel, charset), charset.decode(buffer));buffer.clear();channel.read(buffer, timeout, TimeUnit.SECONDS, null, this);}@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();}});} catch (Exception e) {e.printStackTrace();}}@Overridepublic void failed(Throwable exc, Object attachment) {exc.getStackTrace();}public abstract void channelActive(ChannelHandler ctx);public abstract void channelInactive(ChannelHandler ctx);// 读取消息抽象类public abstract void channelRead(ChannelHandler ctx, Object msg);}

服务端测试
启动服务端
在这里插入图片描述
在这里插入图片描述

BIO


目录结构如下
在这里插入图片描述

客户端


public class BioClient {public static void main(String[] args) {try {Socket socket = new Socket("192.168.2.178", 7397);System.out.println("itstack-demo-netty bio client start done. {关注公众号:bugstack虫洞栈 | 欢迎关注&获取源码}");BioClientHandler bioClientHandler = new BioClientHandler(socket, Charset.forName("utf-8"));bioClientHandler.start();} catch (IOException e) {e.printStackTrace();}}
}

消息处理器

public class BioClientHandler extends ChannelAdapter {public BioClientHandler(Socket socket, Charset charset) {super(socket, charset);}@Overridepublic void channelActive(ChannelHandler ctx) {System.out.println("链接报告LocalAddress:" + ctx.socket().getLocalAddress());ctx.writeAndFlush("hi! 我是码农明哥 BioClient to msg for you \r\n");}@Overridepublic void channelRead(ChannelHandler ctx, Object msg) {System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n");}
}

服务端

public class BioServer extends Thread {private ServerSocket serverSocket = null;public static void main(String[] args) {BioServer bioServer = new BioServer();bioServer.start();}@Overridepublic void run() {try {serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(7397));System.out.println("com.lm.netty01.bio bio server start done. {关注码农明哥| 欢迎关注&获取源码}");while (true) {Socket socket = serverSocket.accept();BioServerHandler handler = new BioServerHandler(socket, Charset.forName("GBK"));handler.start();}} catch (IOException e) {e.printStackTrace();}}
}

消息处理器


public class BioServerHandler extends ChannelAdapter {public BioServerHandler(Socket socket, Charset charset) {super(socket, charset);}@Overridepublic void channelActive(ChannelHandler ctx) {System.out.println("链接报告LocalAddress:" + ctx.socket().getLocalAddress());ctx.writeAndFlush("hi! 我是码农明哥 BioServer to msg for you \r\n");}@Overridepublic void channelRead(ChannelHandler ctx, Object msg) {System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n");}
}

适配器

public abstract class ChannelAdapter extends Thread {private Socket socket;private ChannelHandler channelHandler;private Charset charset;public ChannelAdapter(Socket socket, Charset charset) {this.socket = socket;this.charset = charset;while (!socket.isConnected()) {break;}channelHandler = new ChannelHandler(this.socket, charset);channelActive(channelHandler);}@Overridepublic void run() {try {BufferedReader input = new BufferedReader(new InputStreamReader(this.socket.getInputStream(), charset));String str = null;while ((str = input.readLine()) != null) {channelRead(channelHandler, str);}} catch (IOException e) {e.printStackTrace();}}// 链接通知抽象类public abstract void channelActive(ChannelHandler ctx);// 读取消息抽象类public abstract void channelRead(ChannelHandler ctx, Object msg);
}

BIO测试
启动服务端

在这里插入图片描述
在这里插入图片描述

NIO


目录结构如下
在这里插入图片描述
客户端

public class NioClient {public static void main(String[] args) throws IOException {Selector selector = Selector.open();SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);boolean isConnect = socketChannel.connect(new InetSocketAddress("192.168.2.178", 7397));if (isConnect) {socketChannel.register(selector, SelectionKey.OP_READ);} else {socketChannel.register(selector, SelectionKey.OP_CONNECT);}System.out.println("com.lm.netty01.nio nio client start done. {关注码农明哥 | 欢迎关注&获取源码}");new NioClientHandler(selector, Charset.forName("GBK")).start();}
}

消息处理器

public class NioClientHandler  extends ChannelAdapter {public NioClientHandler(Selector selector, Charset charset) {super(selector, charset);}@Overridepublic void channelActive(ChannelHandler ctx) {try {System.out.println("链接报告LocalAddress:" + ctx.channel().getLocalAddress());ctx.writeAndFlush("hi! 我是,码农明哥 NioClient to msg for you \r\n");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void channelRead(ChannelHandler ctx, Object msg) {System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n");}
}

服务端

public class NioServer {private Selector selector;private ServerSocketChannel socketChannel;public static void main(String[] args) throws IOException {new NioServer().bind(7893);}public void bind(int port) {try {selector = Selector.open();socketChannel = ServerSocketChannel.open();socketChannel.configureBlocking(false);socketChannel.socket().bind(new InetSocketAddress(port), 1024);socketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("com.lm.netty01.nio server start done. {关注码农明哥 | 欢迎关注&获取源码}");new NioServerHandler(selector, Charset.forName("GBK")).start();} catch (IOException e) {e.printStackTrace();}}}

消息处理器

public class NioServerHandler extends ChannelAdapter {public NioServerHandler(Selector selector, Charset charset) {super(selector, charset);}@Overridepublic void channelActive(ChannelHandler ctx) {try {System.out.println("链接报告LocalAddress:" + ctx.channel().getLocalAddress());ctx.writeAndFlush("hi! 我是码农明哥 NioServer to msg for you \r\n");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void channelRead(ChannelHandler ctx, Object msg) {System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);ctx.writeAndFlush("hi 我已经收到你的消息Success!\r\n");}}

Nio测试
启动NioServer
在这里插入图片描述
在这里插入图片描述
好了到这里就结束了基础的netty学习,大家一定要跟着动手操作起来。需要的源码的 可私信我获取;
重要:
给大家构建了个资源群 欢迎圈友携朋友一起加入 大家需要的si我进。

相关文章:

netty之基础aio,bio,nio

前言 在Java中&#xff0c;提供了一些关于使用IO的API&#xff0c;可以供开发者来读写外部数据和文件&#xff0c;我们称这些API为Java IO。IO是Java中比较重要知识点&#xff0c;且比较难学习的知识点。并且随着Java的发展为提供更好的数据传输性能&#xff0c;目前有三种IO共…...

在找工作吗?给你一个AI虚拟面试官助力你提前准备面试

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 让AI点亮我们的生活&#xff0c;是Shelly对…...

@KafkaListener注解中containerFactory属性的作用

在使用Spring Kafka时&#xff0c;containerFactory 属性是 KafkaListener 注解中的一个选项&#xff0c;它允许你指定一个 ContainerFactory Bean 的名称。这个 ContainerFactory 负责创建和管理 Kafka 消息监听容器。 以下是 containerFactory 属性的一些关键作用&#xff1…...

1006C简单题(计数式子的组合意义 + dp式子联立)

http://cplusoj.com/d/senior/p/SS241006C 对于这个式子&#xff0c;我们可以从它的组合意义入手。 假设我们有 n 1 n1 n1 个白球要染色&#xff0c;中间有一个绿球&#xff0c;绿球左边有 a a a 个红球&#xff0c;右边有 b b b 球。染完后绿球左边每个白球有 x x x 的贡…...

千益畅行,旅游创业新模式的创新与发展

旅游创业的时代背景与旅游卡的崛起&#xff0c;在当今快节奏的时代&#xff0c;旅行成为人们生活中的重要部分&#xff0c;随着科技发展和市场需求的变化&#xff0c;旅游创业项目中的旅游卡应运而生。 其中&#xff0c;“千益畅行” 旅游卡作为新兴力量&#xff0c;在共享经济…...

单调栈day54|42. 接雨水(高频面试题)、84. 柱状图中最大的矩形、两道题思维导图的汇总与对比

单调栈day54|42. 接雨水&#xff08;高频面试题&#xff09;、84. 柱状图中最大的矩形、两道题思维导图的汇总与对比 42. 接雨水84. 柱状图中最大的矩形两道题思维导图的汇总与对比 42. 接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱…...

关于Excel将列号由字母改为数字

将Excel的列表由字母改为数字 步骤&#xff1a; 文件-选项-公式-勾选“使用公式”中的“R1C1引用样式(R)”-确定即可 部分步骤图示 设置前的样子 设置后的样子 虽然现在还不清楚在xlwings操作Excel时有什么作用&#xff0c;先留着吧。...

曾黎第二次受邀巴黎时装周看秀 为新疆棉代言引人瞩目

近日&#xff0c;演员曾黎受邀出席巴黎时装周Stella McCartney 2025春夏大秀&#xff0c;她身穿品牌25早春“超季”新装登场&#xff0c;干练的摩登蓝色西服&#xff0c;自信优雅&#xff0c;温婉大气&#xff0c;手提链条黑包上面绑着的一朵新疆棉花十分抢眼&#xff0c;成为全…...

No.6 笔记 | Linux操作系统基础:全面概览与核心要点

1. 简介与历史 1.1 起源 创始人&#xff1a;Linus Torvalds&#xff08;芬兰赫尔辛基大学学生&#xff09;初衷&#xff1a;设计一个替代Minix的全功能Unix操作系统首次发布&#xff1a;1991年10月5日&#xff0c;Linux v0.01版本 2. Linux特点 多用户多任务&#xff1a;用…...

MySQL之分库分表后带来的“副作用”你是怎么解决的?

目录标题 一、垂直分表后带来的隐患二、水平分表后带来的问题1.多表联查问题2.增删改数据问题3.聚合操作问题 三、垂直分库后产生的问题1.跨库join问题2.分布式事务问题3.部分业务库依然存在的性能问题 四、水平分库后需要解决的问题1.聚合操作和连表问题2.数据分页问题3.ID主键…...

【Python】Python-JOSE:Python 中的 JSON Web Token 处理库

Python-JOSE 是一个用于处理 JSON Web Token (JWT) 和 JOSE (JSON Object Signing and Encryption) 标准的 Python 库。它支持对 JWT 进行签名、加密、解密和验证等操作&#xff0c;是处理基于 OAuth 2.0 和 OpenID Connect 协议的身份验证和授权任务的理想选择。Python-JOSE 实…...

SpringBoot3+Druid YAML配置

背景 Druid连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生&#xff0c;内置强大的监控功能&#xff0c;监控特性不影响性能。功能强大&#xff0c;能防SQL注入&#xff0c;内置Loging能诊断Hack应用行为。现在已经SpringBoot3&#xff0c;Druid的配置也需要随…...

【c语言——指针详解(3)】

文章目录 一、字符指针变量二、数组指针变量1、 数组指针变量是什么&#xff1f;2、 数组指针变量怎么初始化 三、⼆维数组传参的本质四、函数指针变量1、函数指针变量的创建2、函数指针变量的使⽤3、两段有趣的代码1&#xff09;typedef 关键字2&#xff09;typedef和define的…...

QT系统学习篇(2)- Qt跨平台GUI原理机制

一、Qt工程管理 1、新建项目&#xff1a; 我们程序员新建项目对话框所有5类项目模板 Application: Qt的应用程序&#xff0c;包含Qt Quick和普通窗口程序。 Library: 它可以创建动态库、静态库、Qt Creator自身插件、Qt Quick扩展插件。 其他项目: 创建单元测试项目、子目录项…...

运用MinIO技术服务器实现文件上传——在Linux系统上安装和启动(一)

# MinIO 单机版环境搭建详解 ## 1. 简介 随着大数据时代的到来&#xff0c;数据存储的需求日益增大&#xff0c;如何有效地存储和管理大规模的非结构化数据成为许多企业和开发者面临的挑战。MinIO 作为一个高性能、分布式对象存储系统&#xff0c;致力于为用户提供简单、快速…...

Python技术深度探索:从基础到进阶的实践之旅(第一篇)

Python技术深度探索&#xff1a;从基础到进阶的实践之旅&#xff08;第一篇&#xff09; 在编程的世界里&#xff0c;Python以其简洁的语法、强大的库支持和广泛的应用领域&#xff0c;成为了无数开发者心中的“瑞士军刀”。无论是数据分析、机器学习、Web开发&#xff0c;还是…...

利士策分享,旅游是否要舟车劳顿才能尽兴?

利士策分享&#xff0c;旅游是否要舟车劳顿才能尽兴&#xff1f; 国庆假期&#xff0c;当夜幕降临&#xff0c;城市灯火阑珊&#xff0c;一场关于美食与等待的较量悄然上演。 李女士在北京天坛公园附近餐厅的等位经历——前方1053桌的壮观景象&#xff0c;不仅让人咋舌&#xf…...

C++入门——类的默认成员函数(取地址运算符重载)

文章目录 一、const成员函数二、取地址运算符重载总结 一、const成员函数 1.将const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后⾯。2.const实际修饰该成员函数隐含的this指针&#xff0c;表明在该成员函数中不能对类的任何成员进…...

学习记录:js算法(四十九):二叉树的层序遍历

文章目录 二叉树的层序遍历网上思路队列循环 总结 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 图一&#xff1a; 示例 1&#xff1a;如图一 输入&#xff1a;roo…...

【PCB工艺】表面贴装技术中常见错误

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 1、什么是SMT和SMD2、表面贴装技术的优势是什么&#xff1f;3、通孔和表面贴装技术之间的区别是什么&#xff1f;4、焊…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...