目录
Java NIO是基于Selector模型来实现非阻塞IO,Netty底层基于Java NIO实现的,因此也使用了Selector模型。

Selector提供了选择执行已经就绪的任务的能力。从底层看,Selector会轮询Channel是否已经准备好执行每个IO操作。Selector允许单个线程处理多个Channel。
并不是所有的Channel都是可以被Selector复用的,只有抽象类SelectableChannel的子类才能被Selector复用。FileChannel就不能被复用,因其不是SelectableChannel的子类。
SelectableChannel并发安全。

- /*
- *Registers this channel with the given selector, returning a selection
- * key.
- *@param sel
- * The selector with which this channel is to be registered
- *
- * @param ops
- * The interest set for the resulting key
- *
- * @param att
- * The attachment for the resulting key; may be null
- **/
- public final SelectionKey register(Selector sel, int ops)
- public abstract SelectionKey register(Selector sel, int ops, Object att)
可供Selector查询的通道操作主要有四种:
- 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;
Channel和Selector关系确定好之后,一旦Channel处于某种就绪状态,就可以被选择器查询到,使用Selector.select()方法。
获取感兴趣的事件集合:
public abstract int interestOps();
获取通道已经准备就绪的操作的集合:
public abstract int readyOps();
从SelectionKey访问Channel和Selector:
- selectionKey.channel();
- selectionKey.selector();
可以将一个对象或其他信息附着到SelectionKey上:
- selectionKey.attach(theObject);
- selectionKey.attachment();
- channel.register(selector, SelectionKey.OP_READ, theObject)
- Selector selector = Selector.open();
-
- ByteBuffer buffer = ByteBuffer.allocate(16);
- ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
- serverSocketChannel.configureBlocking(false);
- serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
- serverSocketChannel.bind(new InetSocketAddress(8080));
-
- while (true) {
- selector.select();
- Iterator
iterator = selector.selectedKeys().iterator(); - while (iterator.hasNext()) {
- SelectionKey selectionKey = iterator.next();
- if(selectionKey.isAcceptable()) {
- ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();
- SocketChannel socketChannel = channel.accept();
- socketChannel.configureBlocking(false);
- socketChannel.register(selector, SelectionKey.OP_READ);
- }
- if(selectionKey.isReadable()) {
- SocketChannel channel = (SocketChannel) selectionKey.channel();
- channel.read(buffer);
- buffer.flip();
- ByteBufferUtil.debugAll(buffer);
- buffer.clear();
- }
- iterator.remove();
- }
- }
每次迭代记得调用iterator.remove。
Netty是异步的事件驱动网络应用框架。