一、 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.class, Object.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
ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel
{
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();
}