3.NIO选择器(基于NIO的服务器与客户端通讯)

【README】

本文总结自B站《尚硅谷netty》,很不错;


【1】选择器Selector(多路复用器)

【1.1】基本介绍

1)Java 的 NIO,用非阻塞的 IO 方式。可以用一个线程,处理多个客户端连接,就会使用到Selector(选择器);

2)Selector 能够检测多个注册的通道上是否有事件发生(注意:多个Channel以事件的方式可以注册到同一个Selector),如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求;

3)只有在 连接/通道 真正有读写事件发生时,才会进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程;

4)避免了多线程之间的上下文切换导致的开销;

5)特点再说明:

  • 5.1) Netty 的 IO 线程NioEventLoop 聚合了 Selector(选择器,也叫多路复用器*),可以同时并发处理成百上千个客户端连接;
  • 5.2)当线程从某客户端Socket 通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务(即线程不会在没有数据可用的客户端连接上阻塞,而是处理其他客户端请求);
  • 5.3) 线程通常将非阻塞IO 的空闲时间用于在其他通道上执行 IO 操作,所以单独的线程可以管理多个输入和输出通道;
  • 5.4)由于读写操作都是非阻塞的,这就可以充分提升IO线程的运行效率,避免由于频繁I/O阻塞导致的线程挂起;
  • 5.5)一个 I/O 线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升;

【1.2】Selector类相关方法

1)Selector 类是一个抽象类, 常用方法和说明如下:
 

public abstract class Selector implements Closeable {public static Selector open();//得到一个选择器对象public int select(long timeout);// 返回IO操作准备就绪的通道的key个数;// 监控所有注册的通道,当其中有 IO 操作可以进行时,将对应的 SelectionKey 加入到内部集合中并返回,参数用来设置超时时间public Set<SelectionKey> selectedKeys();//从内部集合中得到所有的 SelectionKey
}

【补充】

  • 补充1) SelectionKey 与 Channel  是映射关系;通过SelectionKey 可以获取到 Channel ;
  • 补充2) SelectionKey 是 Selector的一个重要对象;

 【注意事项】
1) NIO中的 ServerSocketChannel功能类似ServerSocket,SocketChannel功能类似Socket ;
2) selector 相关方法说明:

selector.select()//阻塞
selector.select(1000);//阻塞1000毫秒,在1000毫秒后返回;
selector.wakeup();// 唤醒selector
selector.selectNow();// 不阻塞,立马返还

【1.3】 SelectionKey在NIO 体系

1)NIO 非阻塞网络编程原理分析图
NIO 非阻塞网络编程相关的(Selector、SelectionKey、ServerScoketChannel和SocketChannel) 关系梳理图;

 【图解】 服务器采用NIO非阻塞处理客户端请求步骤:

  • Step1)当客户端连接时,会通过ServerSocketChannel  生成 SocketChannel;
  • Step2) 把 SocketChannel注册到Selector上,register(Selector sel, int ops),1个selector上可以注册多个SocketChannel
  • Step3)注册后返回一个SelectionKey,会和该Selector 关联(集合);
  • Step4) Selector 监听通道Channel的select方法,返回有事件发生的通道个数.;
  • Step5)进一步得到各个SelectionKey (有事件发生);
  • Step6)再通过SelectionKey反向获取SocketChannel , 通过方法channel() 得到;
  • Step7)可以通过得到的channel , 完成业务处理;

【2】基于NIO实现服务器端和客户端之间的数据简单通讯

1)服务器代码:

/*** @Description 编写一个 NIO 入门案例,*              实现服务器端和客户端之间的数据简单通讯(非阻塞)* @author xiao tang* @version 1.0.0* @createTime 2022年08月17日*/
public class NIOServer024 {public static void main(String[] args) throws IOException {// 创建 ServerSocketChannel -> ServerSocketServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 得到选择器 selectorSelector selector = Selector.open();// 绑定端口 6666 ,在服务器端监听serverSocketChannel.socket().bind(new InetSocketAddress(6666));// 设置为非阻塞serverSocketChannel.configureBlocking(false);// 把 serverSocketChannel 注册到 Selector,关心事件为 OP_ACCEPTserverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 循环等待客户端连接while (true) {if (selector.select(3000) == 0) { // 没有事件发生System.out.println("服务器等待1秒,无客户端连接");continue;}// 如果返回值大于0, 表示监听到有事件发生,// 1.获取相关的  SelectionKey 集合// 2. selector.selectedKeys 获取关注事件的集合// 3. 通过 selectionKeys 反向获取通道;Set<SelectionKey> selectionKeys = selector.selectedKeys();// 4. 遍历 selectionKeys ,使用迭代器遍历Iterator<SelectionKey> it = selectionKeys.iterator();while (it.hasNext()) {// 获取到 SelectionKeySelectionKey key = it.next();// 根据key 对应的通道,发生的事件做不同处理if (key.isAcceptable()) { // 如果是 OP_ACCEPT,表示有新的客户端连接服务器,则需要产生新的 channel// 给客户端生成一个 SocketChannelSocketChannel socketChannel = serverSocketChannel.accept();// 需要把 SocketChannel 设置为 非阻塞socketChannel.configureBlocking(false);System.out.println("客户端连接成功,生成一个 socketChannel, hashcode=" + socketChannel.hashCode());// 把 SocketChannel 注册到 Selector 上,监听 OP_READ 事件socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));}if (key.isReadable()) {// 只读// 通过key反向获取 ChannelSocketChannel channel = (SocketChannel) key.channel();// 获取到该 Channel 关联的 bufferByteBuffer buffer = (ByteBuffer) key.attachment();// 把channel里的读入到 ByteBufferchannel.read(buffer);System.out.println("客户端:" + new String(buffer.array(), StandardCharsets.UTF_8));}// 手动从集合中移除 selectionKey,防止重复操作it.remove();}}}
}

2)客户端:

/*** @Description NIO 客户端* @author xiao tang* @version 1.0.0* @createTime 2022年08月17日*/
public class NIOClient025 {public static void main(String[] args) throws IOException {// 得到一个通道SocketChannel socketChannel = SocketChannel.open();// 设置非阻塞socketChannel.configureBlocking(false);// 提供服务器端的ip 和 端口InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);// 连接服务器if (!socketChannel.connect(inetSocketAddress)) {while(!socketChannel.finishConnect()) {System.out.println("连接需要时间,客户端不会阻塞,可以做其他工作");}}// 若连接到服务器成功,则发送数据到服务器String text = "hello 成都";ByteBuffer byteBuffer = ByteBuffer.wrap(text.getBytes(StandardCharsets.UTF_8));// 发送数据,把buffer中的数据写入到 channelsocketChannel.write(byteBuffer);System.out.println("任意键结束");System.in.read();}
}

【演示效果】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

perplexity 衡量指标_求通俗解释NLP里的perplexity是什么?

高赞回答讲得已经非常通俗易懂&#xff0c;不过由于自然语言处理的发展&#xff0c;出现了许多不同类型的模型&#xff0c;对困惑度这个指标的计算方法颇有不同(包括前面的高赞回答也只是展开了一个子集)&#xff0c;常常让人摸不着头脑。所以这个回答旨在尽量全面地梳理不同语…

C#在Linux上的开发指南

本人才疏学浅&#xff0c;在此记录自己用C#在Linux上开发的一点经验&#xff0c;写下这篇指南。&#xff08;给想要在Linux上开发C#程序的朋友提供建议&#xff09; 目前在Linux上跑的网站&#xff1a;http://douxiubar.com | http://douxiubar.com/AdminLogin/Index&#xff0…

Oracle入门(十四E)之条件表达式case和deocde函数

一、表达式&#xff08;1&#xff09;条件表达式 共有两种条件表达式&#xff0c;即 CASE 表达式和DECODE 表达式。就 CASE 比较两个表达式而言&#xff0c;该表达式在逻辑上等效于之前学习的NULLIF 函数。如果两个表达式相等&#xff0c;则返回null&#xff0c;如果不相等&…

4.基于NIO的群聊系统

【README】 1.本文总结自B站《netty-尚硅谷》&#xff0c;很不错&#xff1b; 2.文末有错误及解决方法&#xff1b; 【1】群聊需求 1&#xff09;编写一个 NIO 群聊系统&#xff0c;实现服务器端和客户端之间的数据简单通讯&#xff08;非 阻塞&#xff09; 2&#xff09;实…

构建高性能.NET应用之配置高可用IIS服务器-第二篇 IIS请求处理模型

在IIS 中&#xff0c;Http监听者(http.sys)和请求处理者由两个系统服务在控制着。一个是WWW 服务&#xff0c;另外一个就是Windows Process Activation。 对于WWW服务&#xff0c;它主要是监控IIS的配置文件&#xff0c;将新的配置信息用到HTTP.sys和WAS上。同时它也维持一些性…

Oracle入门(十四F)之PL/SQL定义变量

一、变量介绍 &#xff08;1&#xff09;变量的使用可以使用变量&#xff1a; 临时存储数据存储值的操作可重用性&#xff08;2&#xff09;PL&#xff0f;SQL中的变量处理变量是&#xff1a; 在声明部分中声明和初始化在可执行部分中使用和分配新值变量可以是&#xff1a;作为…

小米手环nfc门卡摸拟成功后不能开门_如何使用小米手环5 NFC版进行门卡模拟(如公司门禁卡、小区门禁卡、学校门禁卡等)?...

由于本人最近购入了小米手环5 NFC版&#xff0c;所以对小米手环模拟门禁卡比较清楚一点。说一下用该手环模拟门禁的方法吧&#xff0c;我本人模拟的是学校公寓的门禁卡&#xff0c;不过学校的门禁卡是加密卡&#xff0c;可能操作起来稍微比不加密的门禁卡麻烦一点&#xff0c;因…

5.NIO零拷贝与传统IO的文件传输性能比较

【README】 1.本文总结自B站《netty-尚硅谷》&#xff0c;很不错&#xff1b; 2.本文部分内容参考自 NIO效率高的原理之零拷贝与直接内存映射 - 腾讯云开发者社区-腾讯云 【1】零拷贝原理 【1.1】传统IO的文件拷贝 【图解】 step1&#xff09;调用 sys_read系统调用&#…

二进制漏洞利用与挖掘_二进制各种漏洞原理实战分析总结

本部分将对常见的二进制漏洞做系统分析&#xff0c;方便在漏洞挖掘过程中定位识别是什么类型漏洞&#xff0c;工欲善其事&#xff0c;必先利其器。0x01栈溢出漏洞原理栈溢出漏洞属于缓冲区漏洞的一种&#xff0c;实例如下&#xff1a;编译后使用windbg运行直接运行到了地址0x41…

Oracle入门(十四H)之良好的编程实践

一、为什么要学习它 好的编程实践是技巧&#xff0c;可以按照创建最好的代码可能。 编程实践涵盖了一切从代码更多可以用更快的速度创建代码性能。 软件工程团队通常会遵循风格指导让团队中的每个人使用相同的技术。 这使它更容易阅读和修改编写的代码其他。二、编程实践已经学…

微软.NET 正式劈腿成功,横跨所有平台

.NET官方博客宣布了《Announcing .NET Core RC2 and .NET Core SDK Preview 1》&#xff0c;正式如期发布了.NET Core RC2, 现在可以放心的基于.NET Core 构建 ASP.NET Core, console apps 和 class libraries for Windows, OS X and Linux。这里贴张图表达下他们之间的关系: …

2.BIO与NIO区别

【README】 1.本文总结自B站《netty-尚硅谷》&#xff0c;很不错&#xff1b;2.本文介绍 BIO&#xff0c; NIO的知识&#xff1b;【1】BIO&#xff08;传统java IO模型&#xff09; 1&#xff09;BIO-Blocking IO&#xff1a;同步阻塞&#xff0c;服务器实现模式为一个连接一…

k8s往secret里导入证书_K8S之Secret

简介secret顾名思义&#xff0c;用于存储一些敏感的需要加密的数据。这些数据可能是要保存在pod的定义文件或者docker的镜像中。把这些数据通过加密的方式存放到secrets对象中&#xff0c;可以降低信息泄露的风险。在secret中存储的数据都需要通过base64进行转换加密后存放。创…

Oracle入门(十四G)之PL / SQL中检索数据

一、PL / SQL中检索数据 &#xff08;1&#xff09;PL / SQL中的SQL语句可以在PL / SQL中使用以下几种SQL语句&#xff1a;•SELECT从数据库检索数据。•DML语句&#xff0c;例如INSERT&#xff0c;UPDATE和DELETE&#xff0c;以更改数据库中的行。•事务控制语句&#xff0c;例…

.NET Core 1.0 CentOS7 尝试

昨天宣布 ASP.NET Core RC2&#xff0c;据说差不多稳定了&#xff0c;以后不会有大改了。 参考:https://blogs.msdn.microsoft.com/webdev/2016/05/16/announcing-asp-net-core-rc2/ 一、环境装备 等待很久了&#xff0c;高兴之余昨晚安装一个CentOS系统&#xff0c;版本如下&a…

6.netty线程模型-Reactor

【README】 1..本文部分内容翻译自&#xff1a; [Netty] Nettys thread model and simple usage 2.netty模型是以 Reactor模式为基础的&#xff0c;具体的&#xff0c;netty使用的是 主从Reactor多线程模型&#xff1b; 3.先介绍了 Reactor线程模型&#xff1b;后介绍了 Ne…

python mac读取 文件属性_从Python获取和设置mac文件和文件夹查找器标签

macfile模块是^{}模块的一部分&#xff0c;在"2006-11-20 0.2.0"中被重命名为mactypes使用此模块&#xff0c;以下两个函数可用于获取和设置appscript 1.0版的查找器标签&#xff1a;from appscript import appfrom mactypes import File as MacFile# Note these lab…

Oracle入门(十四.1)之PL / SQL简介

一、PL / SQL描述程序语言扩展到SQL&#xff1a; •允许将基本程序逻辑和控制流与SQL语句组合在一起。 •是Oracle专有编程语言。- 它只能用于Oracle数据库或工具。二、程序语言扩展到SQL•是一种程序语言。 - 当遵循一系列指令时会产生结果。 •是3GL&#xff08;第三代编程语…

构建高性能.NET应用之配置高可用IIS服务器-第三篇 IIS中三个核心组件的讲解(上)

今天的文章的比较的容易&#xff0c;主要讲述IIS中三个比较重要的组件&#xff1a;协议监听者(Protocol Listeners)&#xff0c;WWW服务(World Wide Web Publishing Service)和WAS(Windows Process Activation Service)&#xff0c;理解这三个组件的功能&#xff0c;是理解IIS…

7.netty服务器中提交任务到NioEventLoop(Nio事件循环执行线程)

【README】 1.本文总结自 B站 《尚硅谷-netty》; 2.NioEventLoop实际上是一个提交到线程池的Runnable任务&#xff0c;在while无限循环中运行 taskQueue中的任务&#xff08;串行&#xff09;&#xff1b; 【1】提交任务到NioEventLoop 1&#xff09;NioEventLoop&#xff1…