NIO的基本介绍、核心原理和三大件的使用
public class SelectorServer {
public static void main(String[] args) throws IOException {
//1. 打开一个服务端通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//2. 绑定对应的端口号
serverSocketChannel.bind(new InetSocketAddress(9988));
//3. 通道默认是阻塞的,需要设置为非阻塞
serverSocketChannel.configureBlocking(false);
//4. 创建选择器
Selector selector = Selector.open();
//5. 将服务端通道注册到选择器上,并指定注册监听的事件为OP_ACCEPT
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("server start...");
while (true){
//6. 检查选择器是否有事件
int select = selector.select(2000);
if (select == 0){
System.out.println("当前没有事件待处理...");
continue;
}
//7. 获取事件集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
//8. 判断事件是否是客户端连接事件()
SelectionKey key = iterator.next();
if (key.isAcceptable()){
//9. 得到客户端通道,并将通道注册到选择器上, 并指定监听事件为OP_READ
SocketChannel socketChannel = serverSocketChannel.accept();
System.out.println("有客户端连接...");
//将通道必须设置为非阻塞的状态,因为selector选择器需要轮询监听每个通道的事件
socketChannel.configureBlocking(false);
//指定监听事件为OP_READ 读就绪事件
socketChannel.register(selector, SelectionKey.OP_READ);
}
//10. 判断是否是客户端读就绪事件()
if (key.isReadable()){
//11. 得到客户端通道,读取数据到缓冲区
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer allocate = ByteBuffer.allocate(1024);
int read = socketChannel.read(allocate);
if (read > 0){
System.out.println("客户端消息:" + new String(allocate.array(), 0, read
, StandardCharsets.UTF_8));
//12. 给客户端回写数据
socketChannel.write(ByteBuffer.wrap("hello,server...".getBytes()));
socketChannel.close();
}
}
//13. 从集合中删除对应的事件, 因为防止二次处理.
iterator.remove();
}
}
}
}