SelectionKey
一个Selector中可以注册多通道,不同通道在选择器中被封装成为SelectionKey对象。
public class SelectionKeyImpl extends AbstractSelectionKey {
/** 通道 **/
final SelChImpl channel;
/** 多路复用器**/
public final SelectorImpl selector;
private int index;
/** 感兴趣的事件 **/
private volatile int interestOps;
/** 就绪的事件**/
private int readyOps;
从SelectionKeyImpl定义可以看出相同通道注册多次感兴趣选择键对应到Selector中SelectionKey对象是同一个。
SocketChannel ch1 = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
serverSocketChannel.close();
SelectionKey register3 = socketChannel.register(selector, SelectionKey.OP_READ);
SelectionKey register4 = socketChannel.register(selector, SelectionKey.OP_WRITE);
SocketChannel ch2 = serverSocketChannel2.accept();
socketChannel.configureBlocking(false);
SelectionKey register3 = socketChannel.register(selector, SelectionKey.OP_READ);
image
常用案例
@Test
public void test_selectionKey_server() throws Exception {
/** 实例化一个选择器对象 **/
Selector selector = Selector.open();
/** 创建服务器套接字通道 ServerSocketChannel **/
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
/** 绑定监听 InetSocketAddress **/
serverSocketChannel.bind(new InetSocketAddress("localhost", 8888));
/** 设置为非阻塞IO模型 **/
serverSocketChannel.configureBlocking(false);
Object object = new Object();
/** 将serverSocketChannel通道注册到selector选择器中,并设置感兴趣的事件OP_ACCEPT**/
SelectionKey register1 = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT,object);
/** 获取通道SelectionKey对象中的通道 **/
System.out.println(register1.channel().equals(serverSocketChannel));
/** 获取通道SelectionKey对象绑定到选择器中的附件对象**/
System.out.println(register1.attachment().equals(object));
/** 获取通道SelectionKey对象中选择器 **/
System.out.println(register1.selector().equals(selector));
/** 获取通道SelectionKey对象中感兴趣的事件 **/
System.out.println((register1.interestOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT);
boolean is_Run = true;
while (is_Run) {
/** 阻塞等待事件到达**/
selector.select();
/** 获取到达事件SelectionKey集合**/
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
/** 遍历SelectionKey**/
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
/** 从SelectionKey获取对应通道ServerSocketChannel**/
serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel accept = serverSocketChannel.accept();
/** 获取通道SelectionKey对象中就绪的事件 **/
System.out.println((register1.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT);
}
}
}
}
@Test
public void test_selectionKey_client() throws Exception {
/** 实例化一个选择器对象 **/
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("localhost", 8888));
socketChannel.register(selector, SelectionKey.OP_CONNECT);
boolean is_Run = true;
while (is_Run) {
/** 阻塞等待事件到达**/
selector.select();
/** 获取到达事件SelectionKey集合**/
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
/** 遍历SelectionKey**/
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isConnectable()) {
socketChannel = (SocketChannel) key.channel();
while (!socketChannel.finishConnect()){
}
}
}
}
}
网友评论