说到netty,不得不提的一个就是Java NIO。本文主要介绍JAVA NIO涉及到的一些基础概念以及对JAVA NIO的开发过程进行简单介绍。
基本概念
Java NIO,一般称为非阻塞IO,它基于多路复用模型。它有三个基本的概念:Channel(通道),Buffer(缓冲区),Selector(多路复用器)。
channel 通道
channel是一个全双工通道,不同于的流的地方,它可以同时用于读和写。因为它是全双工的,可以比流更好地映射底层操作系统的API,它代表了一个面向流的可监听读写事件的socket。 channel主要分为两大类,分别是用于网络读写的SelectableChannel和用于文件读写的FileChannel,其中SelectableChannel又提供了两个子类,分别是面向服务端的ServerSocketChannel和面向SocketChannel。
Buffer 缓冲区
在 Java NIO中,所有的数据都是通过缓冲区进行处理的。在读取的时候,将数据读取到缓冲区;在写入数据时,也是将数据写入到缓冲区的。最常用是缓冲区是ByteBuffer。
Selector
Selector是Java NIO中的多路复用器。 它的主要作用就是提供已经就绪的任务,Selector会不断轮询注册在其上的Channel,如果某个Channel上有新的连接接入、读和写事件,这个Channel就会被轮询出来,然后通过SelectionKey可以获取整个就绪的Channel集合,进行后续的IO操作。
可以将多个Channel注册到一个Selector上,使用一个线程处理所有的IO事件,也可以将多个Channel注册到多个Selector实例上,利用多线程的高性能处理IO事件。
编程步骤
服务端
Java NIO提供的API较为繁琐,此处就不上代码了,对于多路复用模型,服务端和前文中使用python编写的过程很类似,主要有以下几点:
- 创建一个负责监听新连接的socket
- 通过系统调用得到一个处于就绪状态的连接集合
- 创建一个循环用来轮询这个集合
- 判断事件类型。如果是Accept,则创建新的连接并为其注册事件,如果是读写数据,则作读写处理
下面是Java NIO服务端端的序列图:
- 创建ServerSocketChannel,设置为非阻塞模式
- 设置ServerSocketChannel参数,绑定监听地址
- 创建一个线程,用来轮询多路复用器Selector
- 将ServerSocketChannel注册到Selector,监听SelectionKey.Accept事件
- 在循环中使用Selector.select()获取就绪状态的channel,对事件类型进行判断:
- 如果是Accept事件,则调用ServerSocketChannel.accept()创建新的客户端连接,将其设置成非阻塞模式,并注册到Selector监听感兴趣的操作(read、write)
- 如果是Read事件,则需构造ByteBuffer对象,读取数据包
- 如果是Write事件,则继续发送数据包
客户端
- 创建SocketChannel,设置成非阻塞,设置Tcp参数
- 连接服务端,如果连接成功,则向selector注册读写事件,进行IO操作
- 如果连接失败,则向selector注册CONNECT事件,轮询处理。
总结
Java NIO提供的接口使用起来较为复杂,netty封装了更为简单的方法,并且netty自身的线程模型也是实现更性能的关键,后面会做介绍。
网友评论