概述
java NIO属于epoll水平触发
NIO调用 | linux epoll实现 |
Selector.open() | epoll_create |
ServerSocketChannel#register() | 将事件存储EpollArrayWrapper的成员变量eventsLow和eventsHigh中 |
Selector#select() | 从eventsLow和eventsHigh中取出事件,调用epoll_ctl ,设置为水平触发, 并epoll_wait |
ServerSocketChannel的使用示例如下:
//1. 获取服务端通道
ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.bind(new InetSocketAddress(9898));
//2. 设置为非阻塞模式
ssChannel.configureBlocking(false);
//3. 打开一个监听器
Selector selector = Selector.open();
//4. 向监听器注册接收事件
ssChannel.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0) {
//5. 获取监听器上所有的监听事件值
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
//6. 如果有值
while (it.hasNext()) {
//7. 取到SelectionKey
SelectionKey key = it.next();
//8. 根据key值判断对应的事件
if (key.isAcceptable()) {
//9. 接入处理
SocketChannel socketChannel = ssChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
//10. 可读事件处理
SocketChannel channel = (SocketChannel) key.channel();
readMsg(channel);
}
//11. 移除当前key
it.remove();
}
}
ServerSocketChannel.open()方法源码分析
底层是调用SelectorProvider#openServerSocketChannel()方法
/**
* Opens a server-socket channel.
*
* <p> The new channel is created by invoking the {@link
* java.nio.channels.spi.SelectorProvider#openServerSocketChannel
* openServerSocketChannel} method of the system-wide default {@link
* java.nio.channels.spi.SelectorProvider} object.
*
* <