Java NIO Selector 演示
一、基本参数
1.属性
SelectionKey: 通过select方法监听通道事件,有事件发生时将该通道添加到SelectionKey集合并返回;遍历SelectionKey可获得对应通道
2.方法
select() 阻塞,直到至少有一个事件发生
select(time) 阻塞time毫秒数,没有事件就返回
wakeup() 唤醒
selectNow() 不阻塞,立即返回
3.流程
1.当 Client 连接时,ServerSocketChannel 得到 SocketChannel
2.SocketChannel 注册到 Selector 上,一个 Selector 可以注册多个 SocketChannel
3.注册后返回一个 SelectionKey 将 Selector 和 SocketChannel 关联
4.Selector 通过 select 方法监听事件 OP_READ OP_WRITE OP_CONNECT OP_ACCEPT
5.获取有事件发生的 SelectionKey ,通过channel方法获取对应 SocketChannel,进行业务处理
二、通信演示
1.服务端
package com.example.netty.io.nio;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
public class NIOServer {
public static void main(String[] args) throws Exception {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
Selector selector = Selector.open();
serverSocketChannel.socket().bind(new InetSocketAddress(7800));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true){
if (selector.select(1000)==0){
continue;
}
Set<SelectionKey> selectionKeySet = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeySet.iterator();
while (iterator.hasNext()){
SelectionKey k = iterator.next();
if(k.isAcceptable()){
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
System.out.println("客户端连接成功,生成了一个 SocketChannel : " + socketChannel.hashCode());
}
if (k.isReadable()){
SocketChannel channel = (SocketChannel)k.channel();
ByteBuffer buffer = (ByteBuffer)k.attachment();
int read = channel.read(buffer);
String message = new String(buffer.array(), StandardCharsets.UTF_8);
System.out.println("From Client Message : " + message.trim());
if (read==-1){
channel.close();
}
}
iterator.remove();
}
}
}
}
2.客户端
package com.example.netty.io.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
public class NIOClient {
public static void main(String[] args) throws IOException {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",7800);
if(!socketChannel.connect(inetSocketAddress)){
while (!socketChannel.finishConnect()){
System.out.println("因为连接需要时间 客户端不会阻塞 可以处理其他工作...");
}
}
String str = "hello moon";
ByteBuffer buffer = ByteBuffer.wrap(str.getBytes(StandardCharsets.UTF_8));
socketChannel.write(buffer);
buffer.clear();
buffer.flip();
System.in.read();
}
}
3.调试 先启动服务 在启动客户端
