`
tangay
  • 浏览: 94031 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java NIO 研究

阅读更多

 

No-BlockBlock IO 的区别:

 

一个典型的网络通讯步骤为: open (新建socket Chanel )--> connect( 尝试建立连接) --> accept( 连接被接受) --> read( 读取请求) send (输出结果)--> close( 连接关闭)

 

对于一个No-Block 的网络IO ,上面的每一步都是会马上返回的,当然返回的结果可能为null ,可能不为null ,这个要看下上文(context )决定。一般情况下,我们都是需要不为null 的结果,这个就需要我们在适当的时机,执行适当的步骤,这样就会得到我们想要的结果。何为适当的时机?这个下面会讲。

 

对于一个block 的网络IO ,上面的每一步执行的时候,如果没到适当的时机,当前线程就会被block 住,直到适当的时机,返回给你确定的结果。

 

当然对与No-Block 或者Block IO ,上面的每一步都有可能会抛出IOException 异常的。

 

NIO 编程接触的几个关键概念:

 

Buffer :是一块连续的内存块,是 NIO 数据读或写的中转地。Buffer 这篇blog 暂时略过不讲。

 

Chanel :数据的源头或者数据的目的地,用于向 buffer 提供数据或者读取 buffer 数据 ,异步 I/O 支持。

 

注意chanel2 类,一种叫SocketChanel, 一种叫ServerSocketChanel ,看名字我们就知道,一类是普通的socket chanelclient 端和服务器端都用的,一类是专门用在server 端的。当然这个界限也不是绝对的,互为clientserver 的情况也是存在的。

 

Selector chanel 事件的侦听者, 它能检测一个或多个通道 (channel) 上的事件,并将事件分发出去。使用一个 select 线程就能监听多个通道上的事件,并基于事件驱动触发相应的响应。

 

SelectionKey chanel 上发生的事件, 包含了事件的状态信息和时间以及对应的 chanel

 

 

Chanel 的状态:

可连( Connectable ):当一个 Chanel 完成 socket 连接操作已完成或者已失败放弃时

能连( Acceptable ):当一个 Chanel 已经准备好接受一个新的 socket 连接时

可读( Readable ):当一个 Chanel 能被读时

可写( Writable ):当一个 Chanel 能被写时

 

结合对照上面的网络通讯步骤我们可以有以下推导出的结论:

当一个 Server Chanel Connectable 时, client 端尝试 connect 才会成功。

当一个 Server Chanel Acceptable 时, client 的连接请求被真正受理,一个新的 chanel 会被生成,并且记录了 localAdrress remoteAddress. 为进一步读写做准备。

当一个 Chanel Readable 时,我们从这个 Chanel 中读取数据才会成功。

当一个 Chanel Writable 时,我们往这个 Chanel 中写数据才会成功。

 

记住一点,对于一个 No-Block Chanel 来说,上面 4 个操作都会马上返回或者抛出 IOException ,但是是不是成功就难说了,前面就说了,我们在一个 Chanel 做操作的时候,我们要密切关注 Chanel 的当前状态。只有在知道 Chanel 的当前状态时,我们才能在这个 Chanel 上做最适当的操作。

 

聪明的你可能马上就会想到,要是你操作的 Chanel 的状态的转换信息能被你抓取,这些问题就迎刃而解了。对啦, NIO 就是这样设计的。一个 Chanel 可以注册一个 Selector (就像一个事件侦听器),而且你还要告知你想要要侦听的状态。用一段代码来说明下:

selector = SelectorProvider.provider().openSelector();

serverChannel1 = ServerSocketChannel.open();

serverChannel1.configureBlocking(false);

InetSocketAddress isa = new InetSocketAddress("localhost", 9999);

serverChannel1.socket().bind(isa);

serverChannel1.register(selector, SelectionKey.OP_ACCEPT);

 

这段代码的意思就是我们打开了一个 ServerChanel ,侦听本机的 9999 端口,并且新建了一个 Selector, 然后这个 ServerChanel 注册了这个 Selector ,并且指定了它感兴趣的状态类型是 OP_ACCEPT. 这样有什么效果呢?

注意红色那句,这句意思是selector要求serverChannel1状态为acceptable的时候把这个消息告诉selector.

效果就是:

当这个 ServerChanel 状态为 Acceptable 时, Selector 就会收到一个消息,这个消息当然就是一个 SelectionKey 对象。调用 Selector selectedKeys ()方法,我们就能得到所有 Chanel 发送过来的消息。

 

因为 SelectionKey 包含 事件的状态,时间以及对应的 Chanel ,很自然的,我们遍历这个 Set<SelectionKey>, 根据 SelectionKey 的状态,就能在相应的 Chanel 做正确的操作。比如,能读的时候我们就读,能写的时候我们就写。

 

 

最后讲讲 Server 端和 Client 编程的一般步骤:

 

对于 Client 来一般是这样的:

InetSocketAddress isa = new InetSocketAddress(host, port);

SocketChannel sc = null;

sc = SocketChannel.open();

sc.connect(isa);

sc.write(data);

Sc.read(buff);

 

构造一个 InetSocketAddress 对象 --> open --> connect --> write --> read

 

注意这里用的不是 No-Block 的方式,因为 client 如果没有得到 server 端的正确回应的话就采取下一步操作无疑是没有意义的。

 

 

Server 端:

selector = SelectorProvider.provider ().openSelector();

serverChannel = ServerSocketChannel.open ();

serverChannel .configureBlocking( false );

InetSocketAddress isa = new InetSocketAddress( "localhost" , 9999 );

serverChannel .socket().bind(isa);

serverChannel .register( selector , SelectionKey. OP_ACCEPT );

 

构造一个 Selector --> 打开一个 serverSocketChanel --> 设定 serverSocketChanel no-block--> bind serverSocketChanel 到一个 host port --> register Selector 并告知感兴趣的状态类型转换。

 

SelectionKey Set 上遍历操作:

 

while (true) {

selector.select();

      Iterator selectedKeys = this.selector.selectedKeys().iterator();

     while (selectedKeys.hasNext()) {

        SelectionKey key = (SelectionKey) selectedKeys.next();

          selectedKeys.remove();

         if (!key.isValid()) {

         continue;

          }

         if (key.isAcceptable()) {

         accept(key);

         } else if (key.isReadable()) {

               read(key);

         } else if (key.isWritable()) {

                write(key);

         }

}

}

 

在这个循环里面我们会根据 SelectionKey 的状态,采取不同的操作的。当连接被 accepted 时, 一个新的 chanel 会被生成,并且记录了 localAdrress remoteAddress. 为进一步读写做准备。 accept 函数如下:

 

public void accept(SelectionKey key) throws IOException {

        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

        SocketChanel socketChannel1 = serverSocketChannel.accept();

        socketChannel1.configureBlocking(false);

        socketChannel1.register(selector, SelectionKey.OP_READ);

}

这里新的 Chanel 被构建,最后同样会注册到 selector 同时要求当这个 Chanel Readable 时,一个 SelectionKey 被放入到 Selector 中。这样上面循环会用 read(key) 来处理这个 SelectionKey.

 

 

 

 

 

分享到:
评论

相关推荐

    Java Nio selector例程

    我研究并实现的Java Nio selector例子。java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server...

    基于JavaNIO的非阻塞通信的研究与实现

    基于JavaNIO的非阻塞通信的研究与实现

    java socket nio 研究

    NULL 博文链接:https://zfms.iteye.com/blog/1535594

    基于Java NIO的高校心理咨询系统的研究与设计.pdf

    基于Java NIO的高校心理咨询系统的研究与设计.pdf

    java nio实战代码.rar

    #资源达人分享计划# java nio从入门到精通的代码详解 主要结合博文进行学习 详情可配合我的博客进行学习 https://blog.csdn.net/weixin_47872288/article/details/120342049

    基于Java NIO实现五子棋游戏.zip

    java课程设计大作业,java、算法练手项目,适合初学java、数据结构的同学拿来学习研究,基于java、GUI开发的小游戏,程序都经过测试,可以直接运行,资源含程序运行所需的源码、资源文件等全部数据,有需要的可放心...

    java.nio(socket异步通讯完整版)

    重新写的Java.nio的socket异步通讯,包含客户端及服务端完整版, 注:解析信息CLASS及进制转换CLASS需要自己去写,项目直接导入,需要自己写一些解析及转换类,这样你才能读懂SOCKET的异步,否则光拿代码没用 ...

    Java Netty技术研究

    近代: java.nio java.niojava.niojava.niojava.niojava.nio 其他: MinaMinaMinaMina,GrizzlyGrizzlyGrizzly GrizzlyGrizzly 为什么不是 为什么不是 MinaMina Mina? 1、都是 Trustin LeeTrustin LeeTrustin Lee ...

    基于Java_NIO_开发高性能并发型服务器程序的研究.pdf

    分析了应用传统阻塞型网络I/O 在进行服务器程序设计时的不足, 在此基础上研究了非阻塞型网络I/O (NIO)的特性以及工作机制,给出了应用NIO 设计高性能并发型服务器程序核心代码,以实现服务器与客户端无阻 塞的、...

    毕业设计:Java研究生训练营项目

    1. 培训内容设计:包括Java编程语言基础、面向对象编程、集合框架、多线程编程、IO与NIO、网络编程、数据库编程、Spring框架、设计模式等诸多模块,需要根据学员的学科背景和研究方向进行合理的内容设计。...

    从NIO到Netty,编程实战出租车905协议-08172347.pdf

    905.4-2014协议,是交通运输部公路科学研究院起草定制的一个协议标准,它也是基于TCP之上的一个应用层传输协议。 第2章,介绍在Socket编程过程中一些基础知识,让大家建立起对这块知识内容的一个整体轮廓; 第3章,...

    java开源包101

    JoSQL(SQLforJavaObjects)为Java开发者提供运用SQL语句来操作Java对象集的能力.利用JoSQL可以像操作数据库中的数据一样对任何Java对象集进行查询,排序,分组。 搜索自动提示 Autotips AutoTips是为解决应用系统对于...

    Netty权威指南 第2版 带书签目录 完整版

    Netty权威指南 第2版 带书签目录 完整版,适合java NIO的研究学习

    基于JAVA的网络棋牌游戏系统的设计

    论文首先论述了系统的研究背景和目标,并对所用到开发工具与关键技术做了简单的介绍。...使用Java语言结合xml技术提高了系统的可靠性和可以移植性,应用NIO技术很大程度上提高系统的网络吞吐量和数据处理能力。

    nio-study:尼奥研究

    nio-study:尼奥研究

    Java网络编程(第三版)中文版.part09.rar

    本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIO API编写超高性能的服务器。它还涵盖了Java对网络代理、Web cookie和URL缓存的支持。 《Java网络编程》不仅仅是对API的解释:它还展示了如何使用...

    java版联机五子棋

    java版联机五子棋,包含服务器端及用户端,服务器端采用nio实现。包含游戏大厅,可查看在线玩家及玩家数据,支持大厅广播及私聊;支持多人同时对战,支持悔棋、认输;支持多人观战;支持查看历史对战记录,支持添加...

    粒子创造宇宙学的两流体解决方案

    研究了由时变引力场结合连续粒子产生驱动的宇宙演化。 在广义相对论的背景下,我们考虑具有两种物质流体的空间平坦,均匀且各向同性的宇宙。 一种流体被赋予重力诱导的“绝热”粒子生成,而第二种流体仅满足能量守恒...

Global site tag (gtag.js) - Google Analytics