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()
判斷鏈接是否正在鏈接狀態