书接上文
上一篇博客中的结尾讲到将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
感谢!