書接上文
上一篇博客中的結尾講到將Channel註冊在某個Selector的管轄範圍之下:
channel.register(selector, SelectionKey.OP_ACCEPT);
由這個register()方法的第二個參數SelectionKey.OP_ACCEPT,我們引出關於SelectionKey的討論。
常量OP_ACCEPT是SelectionKey中一個重要屬性Interest Set中的一個常量,Selector就是通過這個集合來監聽Channel對什麼事件感興趣的,所以register()方法返回一個SelectinKey對象,通過這個對象完成後續的一些偏底層的操作。
首先我們先看一看SelectionKey對象中有哪些屬性:
- Interest Set興趣集合
- Ready Set就緒集合
- Channel通道
- Selector選擇器
- Attach附加對象
Interest Set
監聽的Channel通道觸發了一個事件意思是該事件已經就緒。
一個channel成功連接到另一個服務器稱爲”連接就緒“。
一個server socket channel準備號接收新進入的連接稱爲”接收就緒“。
一個有數據可讀的通道可以說是”讀就緒“。
一個等待寫數據的通道可以說是”寫就緒“。
這四種事件用SelectionKey的四個常量來表示:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- 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選擇就緒的通道以及一個模擬遊戲服務器監聽客戶端玩家上線的一個簡單實例。
參考文章:
http://blog.csdn.net/robinjwong/article/details/41792623#t3
【Java.NIO】Selector,及SelectionKey
感謝!