1. 程式人生 > >Java NIO學習(二)SelectionKey詳解

Java NIO學習(二)SelectionKey詳解

書接上文

上一篇部落格中的結尾講到將Channel註冊在某個Selector的管轄範圍之下

channel.register(selector, SelectionKey.OP_ACCEPT);

由這個register()方法的第二個引數SelectionKey.OP_ACCEPT,我們引出關於SelectionKey的討論。

常量OP_ACCEPT是SelectionKey中一個重要屬性Interest Set中的一個常量,Selector就是通過這個集合來監聽Channel對什麼事件感興趣的,所以register()方法返回一個SelectinKey物件,通過這個物件完成後續的一些偏底層的操作。

首先我們先看一看SelectionKey物件中有哪些屬性:

  1. Interest Set興趣集合
  2. Ready Set就緒集合
  3. Channel通道
  4. Selector選擇器
  5. Attach附加物件

Interest Set

監聽的Channel通道觸發了一個事件意思是該事件已經就緒。
一個channel成功連線到另一個伺服器稱為”連線就緒“。
一個server socket channel準備號接收新進入的連線稱為”接收就緒“。
一個有資料可讀的通道可以說是”讀就緒“。
一個等待寫資料的通道可以說是”寫就緒“。

這四種事件用SelectionKey的四個常量來表示:

  1. SelectionKey.OP_CONNECT
  2. SelectionKey.OP_ACCEPT
  3. SelectionKey.OP_READ
  4. SelectionKey.OP_WRITE

舉例:

//通道註冊讀事件
channel.register(this.selector, SelectionKey.OP_READ);

Ready Set

Ready Set是通道已經準備就緒的操作的集合,在一個選擇後,你會是首先訪問這個Ready Set。

int readySet = selectionKey.readyOps();  

對於Channel中已就緒的事件,我們可以通過下面這種方式去輪詢哪些事件已經就緒,並執行相應的業務操作:

//輪詢所有選擇器接收到的操作
Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> selectionKeyIte=selectionKeys.iterator(); while(selectionKeyIte.hasNext()){ selectionKey = selectionKeyIte.next(); if (key.isAcceptable()){ }else if (key.isConnectable()){ }else if (key.isReadable()){ }else if (key.isWritable()){ } // 刪除已選的key,以防重複處理 selectionKeyIte.remove(); }

Channel通道

我們可以通過SelectionKey物件獲取其監聽的Channel通道:

Channel channel = selectionKey.channel();  

Selector選擇器

我們可以通過SelectionKey物件獲取其所屬的選擇器Selector:

Selector selector = selectionKey.selector();

Attach附加物件

可以將一個物件或者更多的資訊附著到SelectionKey上,這樣就能方便的識別某個給定的通道。例如,可以附加與通道一起使用的Buffer,或是包含聚集資料的某個物件。

selectionKey.attach(theObject);  
Object attachedObj = selectionKey.attachment(); 

結語

本篇部落格講了一些SelectionKey常用的一些屬性和方法,下一篇將詳細的說一下如何通過Selector選擇就緒的通道以及一個模擬遊戲伺服器監聽客戶端玩家上線的一個簡單例項。

參考文章:

感謝!