JAVANIO -选择器 SelectionKey原理和使用

2019-07-25  本文已影响0人  贪睡的企鹅

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()){
                    }
                }
            }
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读