• 第三章—Java NIO编程:(6)SelectionKey、ServerSocketChannel与SocketChannel


    一、 SelectionKey

    1、SelectionKey

    SelectionKey, 表示Selector和网络通道(Channel)绑定的关系。

    以 SelectorImpl 为例,看一下源码:

    public abstract class SelectorImpl extends AbstractSelector {
        //当前 selector 中关注事件的 selectionKey
        protected Set<SelectionKey> selectedKeys = new HashSet();
        
        //当前 selector 中已经注册的 selectionKey
        protected HashSet<SelectionKey> keys = new HashSet();
        private Set<SelectionKey> publicKeys;
        private Set<SelectionKey> publicSelectedKeys;

    ...
    }

    2、相关API

    (1)SelectionKey, 表示 Selector 和网络通道的注册关系, 共四种:

    int OP_READ: 代表读操作, 值为 1

    int OP_WRITE: 代表写操作, 值为 4

    int OP_CONNECT: 代表连接已经建立, 值为 8

    int OP_ACCEPT: 有新的网络连接可以 accept, 值为 16

    源码中:

    public static final int OP_READ = 1 << 0;
    public static final int OP_WRITE = 1 << 2;
    public static final int OP_CONNECT = 1 << 3;
    public static final int OP_ACCEPT = 1 << 4;

    (2)SelectionKey相关方法

    public abstract class SelectionKey {

        protected SelectionKey() { }

        // -- Channel and selector operations -- 通道和选择器操作
        //得到与之关联的通道
        public abstract SelectableChannel channel();

        //得到与之关联的Selector 对象
        public abstract Selector selector();

        public abstract boolean isValid();

        public abstract void cancel();


        // -- Operation-set accessors -- 操作集访问器
        public abstract int interestOps();

        //设置或改变监听事件
        public abstract SelectionKey interestOps(int ops);

        public abstract int readyOps();

        // -- Operation bits and bit-testing convenience methods -- 
        //操作位和位测试便利方法
        public static final int OP_READ = 1 << 0;
        public static final int OP_WRITE = 1 << 2;
        public static final int OP_CONNECT = 1 << 3;
        public static final int OP_ACCEPT = 1 << 4;

        //是否可以读
        public final boolean isReadable() {
            return (readyOps() & OP_READ) != 0;
        }

        //是否可以写
        public final boolean isWritable() {
            return (readyOps() & OP_WRITE) != 0;
        }

        public final boolean isConnectable() {
            return (readyOps() & OP_CONNECT) != 0;
        }

        //是否可以 accept
        public final boolean isAcceptable() {
            return (readyOps() & OP_ACCEPT) != 0;
        }


        // -- Attachments -- 附件

        private volatile Object attachment = null;

        private static final AtomicReferenceFieldUpdater<SelectionKey,Object>
            attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(
                SelectionKey.classObject.class, "attachment"
            )
    ;

        //得到与之关联的共享数据
        public final Object attach(Object ob) {
            return attachmentUpdater.getAndSet(this, ob);
        }

        public final Object attachment() {
            return attachment;
        }

    二、 ServerSocketChannel

    1、ServerSocketChannel

      ServerSocketChannel 在服务器端监听新的客户端 Socket 连接,用于建立与客户端的连接

    2、相关 API

    public abstract class ServerSocketChannel 
    extends AbstractSelectableChannel implements NetworkChannel
    {
        protected ServerSocketChannel(SelectorProvider provider) {
            super(provider);
        }

        //得到一个 ServerSocketChannel 通道
        public static ServerSocketChannel open() throws IOException {
            return SelectorProvider.provider().openServerSocketChannel();
        }
        
        public final int validOps() {
            return SelectionKey.OP_ACCEPT;
        }
        
        // -- ServerSocket-specific operations --特定于 ServerSocket 的操作
        //设置服务器端端口号
        public final ServerSocketChannel bind(SocketAddress local) throws IOException
        
    {
            return bind(local, 0);
        }
        
        public abstract ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException;
        
        
        public abstract <T> ServerSocketChannel setOption(SocketOption<T> name, T value) throws IOException;
        
        public abstract ServerSocket socket();
        
        //接受一个连接, 返回代表这个连接的通道对象
        public abstract SocketChannel accept() throws IOException;
        public abstract SocketAddress getLocalAddress() throws IOException;
        
        //设置阻塞或非阻塞模式, 取值 false 表示采用非阻塞模式
        public final SelectableChannel configureBlocking(boolean block);
        
        //注册一个选择器并设置监听事件
        public final SelectionKey register(Selector sel, int ops)
        
    }

    三、 SocketChannel

    1、SocketChannel

      SocketChannel,网络 IO 通道,具体负责进行读写操作。 NIO 把缓冲区的数据写入通道,或者把通道里的数据读到缓冲区。

    2、相关 API

    public abstract class SocketChannel extends AbstractSelectableChannel implements 
    ByteChannelScatteringByteChannelGatheringByteChannelNetworkChannel
    {

        protected SocketChannel(SelectorProvider provider) {
            super(provider);
        }
        
        //得到一个 SocketChannel 通道
        public static SocketChannel open() throws IOException {
            return SelectorProvider.provider().openSocketChannel();
        }
        
        //设置阻塞或非阻塞模式, 取值 false 表示采用非阻塞模式
        public final SelectableChannel configureBlocking(boolean block);
        
        //连接服务器
        public abstract boolean connect(SocketAddress remote) throws IOException;
        
        //如果上面的方法连接失败, 接下来就要通过该方法完成连接操作
        public abstract boolean finishConnect() throws IOException;
        
        //往通道里写数据
        public int write(ByteBuffer src);
        
        //从通道里读数据
        public int read(ByteBuffer dst);

        //注册一个选择器并设置监听事件, 最后一个参数可以设置共享数据
        public final SelectionKey register(Selector sel, int ops, Object att);
        
        //关闭通道
        public final void close();
    }
  • 相关阅读:
    《程序员代码面试指南》第三章 二叉树问题 先序、中序和后序数组两两结合重构二叉树
    《程序员代码面试指南》第三章 二叉树问题 二叉树节点间的最大距离问题
    《程序员代码面试指南》第三章 二叉树问题 在二叉树中找到一个节点的后继节点
    《程序员代码面试指南》第三章 二叉树问题 通过有序数组生成搜索二叉树
    《程序员代码面试指南》第三章 二叉树问题 判断一个树是搜索二叉树和完全二叉树
    《程序员代码面试指南》第三章 二叉树问题 根据后序数组重建搜素二叉树
    《程序员代码面试指南》第三章 二叉树问题 判断二叉树是否为搜素二叉树
    博弈知识入门引导
    ZZNUOJ-2157: 水滴来袭-【干扰阅读-卡模糊精度1e-8的问题】
    ZZNUOJ-2155-单身man集合-【标程做法:数位DP-1-10^8,提前暴力打表法: 砍时间复杂度到10^5】
  • 原文地址:https://www.cnblogs.com/niujifei/p/15971182.html
Copyright © 2020-2023  润新知