1. SelectorKeys迭代器用完移除
Selector.selectKeys()迭代器用完移除,不然会一直select出来
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
// 这里要移除,不然会一直select出来
iterator.remove();
handleKey(key);
}
2. Key的时间要取消注册
Key的时间要取消注册,不然也会一直select到
if (key.isWritable()) {
SocketChannel channel = (SocketChannel) key.channel();
log.info("与server[{}]通道可写", channel.getRemoteAddress());
// 这里取消key感兴趣的事件,避免写事件一直select到
key.interestOps(key.readyOps() & ~SelectionKey.OP_WRITE);
}
3. 客户端连接问题
客户端连接服务端,一定要先Selector.open() 再执行 channel.connect(),不然会无法select到connectable事件
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9090));
Selector selector = Selector.open();
socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(), 8080));
System.out.println("connect server success....");
socketChannel.register(selector, SelectionKey.OP_CONNECT);
4. 调用attach问题
attach以后还需要register第三个参数传过去,才能在别的渠道用attachment方法获取
selectionKey.attach(attachment);
socketChannel.register(selector, SelectionKey.OP_WRITE, attachment);
5. selector.select(); 调用
selector.select()最好加个时间,比如 selector.select(100); 间隔100ms,select一次。不然会一直阻塞在select那,导致子线程利用socketChannel.register(selector, opt); 无法生效
int select = selector.select(100);
6. 注册事件attachment附件问题
// 清空attachment
socketChannel.register(selector, opt);
// 保留attachment
selectionKey.interestOps(selectionKey.readyOps() | opt)