美文网首页
JAVANIO -选择器 SelectionKey原理和使用

JAVANIO -选择器 SelectionKey原理和使用

作者: 贪睡的企鹅 | 来源:发表于2019-07-25 20:27 被阅读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()){
                    }
                }
            }
        }
    }

相关文章

  • JAVANIO -选择器 SelectionKey原理和使用

    SelectionKey 一个Selector中可以注册多通道,不同通道在选择器中被封装成为SelectionKe...

  • JAVANIO -选择器02 Selector原理和使用

    Selector 概述 Selector 一般称为选择器,用来作为SelectableChannel通道的多路复用...

  • 高并发知识(三)

    可供选择器监控的通道IO事件类型,包括以下四种: (1)可读:SelectionKey.OP_READ (2)可写...

  • Java NIO--Selector

    Selector简介 Selector(选择器)是javaNIO中能检测一到多个NIO通道,并能够知道通道是否为诸...

  • netty源码read

    1. boss event loop 关心SelectionKey.OP_READ | SelectionKey....

  • Java NIO Selector

    1,SelectionKey 1)创建SelectionKey每次channel向selector注册时,会创建一...

  • nio个人研究

    nio中的关键是selecter,这是一个选择器,从代码来看实际上就是一个列表,一个包含SelectionKey的...

  • CSS笔记

    - CSS学习: 1 . 类选择器和id选择器的区别和使用,id选择器只能够用一次,类选择器可以用多次,使用方法是...

  • javaNio认识与使用

    nio是 java new io 的简写 可以代替原来 io所进行的操作 old io 是面向流stream的...

  • css选择器

    HTML选择器 直接使用标签 属性选择器(id,class) *全局选择器 关联选择器 和 组合选择器 实例代码 ...

网友评论

      本文标题:JAVANIO -选择器 SelectionKey原理和使用

      本文链接:https://www.haomeiwen.com/subject/hemkrctx.html