NIO 三大核心
- Channel (通道)
- Buffer (缓冲区)
- Selector (选择器)
模型图
代码演示
package com.xxl.job.admin.mytest;
import java.io.*;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class NioDemo {
public static void main(String[] args) {
try {
// 开启服务端通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// selector 注册器
Selector selector = Selector.open();
// 绑定端口
serverSocketChannel.socket().bind(new InetSocketAddress(6666));
// 设置为非阻塞
serverSocketChannel.configureBlocking(false);
// 把 channel 注册到 selector 上面
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// 循环等待客户端连接
while (true) {
// 查询如果没有事件发生就可以起做其他的操作了,无需阻塞在这里
if (selector.select(1000) == 0) {
System.out.println("服务器等待1s,无连接");
continue;
}
// 返回关注的事件集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
// 针对不同的 selectionKey 去做响应的操作
// 发生了客户端连接事件
if (selectionKey.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
System.out.println("有一个客户端连接成功,hashCode = "+socketChannel.hashCode());
socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
// 发生了服务器读取事件
if (selectionKey.isReadable()) {
SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
ByteBuffer buffer = (ByteBuffer)selectionKey.attachment();
socketChannel.read(buffer);
System.out.println("form 客户端 "+ new String(buffer.array()));
}
}
iterator.remove();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
使用 telnet
命令进行模拟客户端,链接服务器,命令如下:
telnet 127.0.0.1 8080