课程名称: 解锁网络编程之NIO的前世今生
课程章节:第4章 【应用】NIO网络编程实战、第3章 【熟悉】NIO网络编程详解
课程讲师: 张小喜
课程内容:

// 创建Selector Selector selector = Selector.open(); //将channel注册到selector上,监听读事件 SelectionKey selectionKey = serverChannel.register(selector, SelectionKey.OP_READ); // 阻塞等待channel就绪事件发生 int select = selector.select(); // 获取发生就绪事件的channel集合 Set<SelectionKey> selectionKeys = selector.selectedKeys();
NIO编程实现步骤
第一步:创建Selector
第二步:创建ServerSocketChannel,并绑定监听端口
第三步:将Channel设置为非阻塞模式
第四步:将Channel注册到Socketor上,监听连接事件
第五步:循环调用Selector的select方法,监测就绪情况
第六步:调用selectKeys方法获取就绪channel集合
第七步:判断就绪事件种类,调用业务处理方法
第八步:根据业务需要决定是否再次注册监听事件,重复执行第三步操作
// 创建Selector
Selector selector = Selector.open();
// 2. 通过ServerSocketChannel创建channel通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 3. 为channel通道绑定监听端口
serverSocketChannel.bind(new InetSocketAddress(8000));
// 4. **设置channel为非阻塞模式**
serverSocketChannel.configureBlocking(false);
// 5. 将channel注册到selector上,监听连接事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动成功");
while (true) {
// 获取到可用的channel数量
int readyChannel = selector.select();
if (readyChannel == 0) {
continue;
}
// 获取可用channel的集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
// 由于就绪状态的channel都会放到set里,这里获取到之后就可以删除,以防集合一直增加
iterator.remove();
if (key.isAcceptable()) {
acceptHandler(serverSocketChannel, selector);
}
if (key.isReadable()) {
readHandler(key, selector);
}
}
}private void acceptHandler(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException {
// 如果要是接入事件,创建socketChannel
SocketChannel accept = serverSocketChannel.accept();
// 将socketChannel设置为非阻塞工作模式
accept.configureBlocking(false);
// 将channel注册到selector上,监听 可读事件
accept.register(selector, SelectionKey.OP_READ);
// 回复客户端提示信息
accept.write(Charset.forName("UTF-8").encode("atention nnn"));
}
private void readHandler(SelectionKey selectionkey, Selector selector) throws IOException {
// 要从 selectionKey 中获取到已经就绪的channel
SocketChannel channel = (SocketChannel) selectionkey.channel();
// 创建buffer
ByteBuffer allocate = ByteBuffer.allocate(1024);
// 循环读取客户端请求信息
String request = "";
while (channel.read(allocate) > 0) {
allocate.flip();
request += Charset.forName("UTF-8").decode(allocate);
}
channel.register(selector, SelectionKey.OP_READ);
if (request.length() > 0) {
System.out.println(request);
}
}课程收获:
本次实战是以聊天室作为场景,熟悉NIO的常用接口,目前看到NIO更节省内存。
随时随地看视频