`
tangay
  • 浏览: 94677 次
  • 性别: 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...

    JAVA-NIO-DEMO

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于传统IO(基于字节流和字符流)的I/O操作方式。传统的IO模型是阻塞式的,而NIO的核心...请务必仔细研究并实践这些示例,以深化你的Java NIO知识。

    nio.zip_NIO_NewIO_NIO.c_java NIO chm_java nio

    NIO(New IO)是Java平台中用于处理输入/输出操作的一种高级API,它在Java 1.4版本中引入,以替代传统的IO流模型。NIO提供了更高效、更灵活的数据传输方式...建议读者下载并仔细研究,以便更好地利用NIO提升程序性能。

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

    ### 基于Java NIO的非阻塞通信的研究与实现 #### 摘要 本文探讨了Java NIO(New I/O)框架中的非阻塞通信机制,并对其原理及应用进行了深入研究。NIO是一种现代I/O处理方法,通过引入缓冲区、通道和选择器等新概念...

    Java NIO入门的源码

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种I/O模型,旨在提供一种更高效、更具控制力的I/O操作方式。与传统的-blocking I/O(阻塞I/O)相比,NIO的关键在于它...

    java socket nio 研究

    Java Socket和NIO(Non-blocking Input/Output,非阻塞I/O)是Java网络编程中的重要组成部分,它们在处理高并发、低延迟的网络服务时展现出强大的能力。本篇文章将深入探讨这两个概念,并通过示例代码`...

    java nio 异步编程源码

    Java NIO(非阻塞I/O)和AIO(异步I/O)是Java平台中用于提高I/O性能的重要技术。...通过研究这些代码和文档,开发者可以学习如何创建基于NIO和AIO的服务器,如何处理并发连接,以及如何优化性能。

    Large-File-Processing-master_javanio_java大文件处理_

    综上所述,“Large-File-Processing-master_javanio_java大文件处理_”项目涵盖了Java NIO在大文件处理中的核心技术和最佳实践,是学习和研究Java高效处理大文件的宝贵资源。通过深入理解这些知识点,并结合项目中的...

    java socket Bio Nio example

    Java Socket编程是网络通信的核心部分,它提供了进程间通信(IPC)的能力,使得运行在不同设备上的应用程序可以通过网络...在压缩包中的"Socket"文件可能包含了具体的BIO和NIO的Java实现示例,可以进一步学习和研究。

    基于NIO非阻塞的java聊天demo(支持单聊和群聊)

    Java NIO,全称为New Input/Output,是Java在1.4版本引入的一个新特性,用以替代传统的IO模型。...通过深入研究和分析这个项目,开发者能够更好地掌握NIO在实际项目中的应用,提升系统性能和稳定性。

    一个基于java nio的简单的http服务器.zip

    Java NIO(New IO)是Java 1.4版本引入的一个新特性,全称为Non-blocking Input/Output,即非阻塞I/O。...对于想要深入理解Java NIO或想自己动手搭建服务器的开发者来说,这是一个值得研究的项目。

    Java.nio

    Java.nio,全称为Java Non-blocking Input/...而压缩包中的"thread"、"noblock"、"block"可能分别对应于线程管理、非阻塞I/O和阻塞I/O的相关示例或讨论,进一步深入研究这些内容,有助于深化对Java.nio的理解和应用。

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

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

    java nio实战代码.rar

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

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

    ### 基于Java NIO开发高性能并发型服务器程序的研究 #### 一、引言 在互联网技术迅速发展的背景下,服务器程序面临着越来越高的并发访问需求。为了满足这一需求,传统阻塞型网络I/O(Input/Output)逐渐暴露出其在...

    jdk1.6 源码 包含nio等

    通过研究这些源码,开发者不仅可以了解NIO的工作原理,还可以学习到如何更高效地利用Java平台的特性来优化应用程序,这对于提升代码质量和性能至关重要。此外,JDK 1.6的源码也对后续版本的Java NIO改进和增强提供了...

Global site tag (gtag.js) - Google Analytics