BIO、NIO、AIO 内部原理分析
NIO 之 Selector实现原理
NIO 之 ByteBuffer实现原理数组
Java NIO 由如下几个核心部分组成:服务器
在传统IO中,流是基于字节的方式进行读写的。
在NIO中,使用通道(Channel)基于缓冲区数据块的读写。网络
Java NIO的通道相似IO中的流,但又有些不一样:异步
下面是JAVA NIO中的一些主要Channel的实现:socket
FileChannel 是基于文件的Channel。
DatagramChannel、SocketChannel、ServerSocketChannel 都是基于网络流的Channel。编码
下面咱们主要介绍关于基于网络流的SocketChannel 和 ServerSocketChannel 。spa
基于网络流的Channel中提供了register方法。
使用示例:.net
channel.register(selector, Selectionkey.OP_READ, ByteBuffer.allocate(64));
代码的写法感受是要将selector对象注册到channel中。其实正好相反,应该是将channel注册到selector中。
下面经过代码分析:
![将channel 注册到 selector 中]code
channel 的 register 方法server
1.首先判断 selector 中是否已经注册此 channel ,若是注册过就更新注册的事件和attach附件信息。
public final SelectableChannel configureBlocking(boolean block)
Channel 默认使用阻塞模式,经过 configureBlocking 方法能够将该 Channel 设置成非阻塞模式。
//设置成非阻塞模式 channel.configureBlocking(false);
ServerSocketChannel只支持入站链接请求。不提供读取、写入数据功能。
public abstract SocketChannel accept()
accept()能够在阻塞或非阻塞模式下操做。
示例:
public static void blockMode(){ try { ServerSocketChannel serverChannel = ServerSocketChannel.open(); //绑定要监控的端口 serverChannel.bind(new InetSocketAddress(9000)); //获取入站请求socketChannel SocketChannel clientChannel = serverChannel.accept(); ... } catch (Exception e) { } }
示例:
public static void nonBlockMode(){ try { //建立一个selector Selector selector = Selector.open(); //建立一个ServerSocketChannel ServerSocketChannel serverChannel = ServerSocketChannel.open(); //设置成非阻塞模式 serverChannel.configureBlocking(false); //绑定要监控的端口 serverChannel.bind(new InetSocketAddress(9000)); //接受入站请求 serverChannel.accept(); //将 serverChannel 注册到 selector 上 serverChannel.register(selector, SelectionKey.OP_READ); } catch (Exception e) { } }
SocketChannel 类能够读写TCP Socket。数据必须编码到ByteBuffer对象中来完成读写。
示例:
public static void nonSocketChannel() throws Exception { SocketChannel client = SocketChannel.open(); client.configureBlocking(false); client.connet(new InetSocketAddress("192.168.1.10", 9000)); }
public abstract boolean connect(SocketAddress remote)
非阻塞模式下,若是要链接远程服务器必须使用 connect 方法进行链接。
public abstract boolean finishConnect()
阻塞模式:直接返回true,由于在构造SocketChannel的时候已经创建链接了。
非阻塞模式下:必须调用此方法来判断该方法是否已经创建网络链接,只有创建网络链接后才能进行读写操做。
public abstract boolean isConnected()
判断是否已经链接。
public abstract boolean isConnectionPending()
判断链接是否正在链接状态