[Netty] NIO编程模型以及核心组件简介 多路复用示例(五)

框架与中间件 框架与中间件 7609 人阅读 | 0 人回复

image.png

不管是多Reactor还是多线程模式,只是在基本Reactor模式下的扩展,基本原型是不变的。

NIO的编程模型,也是类似如此。

示例

引入多路复用的NIO示例程序。

https://gitee.com/crazybytex/java-code-fragment/blob/master/src/main/java/com/crazybytex/fragment/nio/NioServer.java
package com.crazybytex.fragment.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author 本文作者 程序员潇然 疯狂的字节X https://www.crazybytex.com/
 * @Date 2022/10/27 16:18
 * @Description
 **/
public class NioServer {
    public static void main(String[] args) throws IOException, InterruptedException {

        // 创建NIO ServerSocketChannel
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.socket().bind(new InetSocketAddress(9000));
        // 设置ServerSocketChannel为非阻塞
        serverSocket.configureBlocking(false);
        // 打开Selector处理Channel,即创建epoll
        Selector selector = Selector.open();
        // 把ServerSocketChannel注册到selector上,并且selector对客户端accept连接操作感兴趣
        serverSocket.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务启动成功");

        while (true) {
            // 阻塞等待需要处理的事件发生
            selector.select();

            // 获取selector中注册的全部事件的 SelectionKey 实例
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();

            // 遍历SelectionKey对事件进行处理
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                // 如果是OP_ACCEPT事件,则进行连接获取和事件注册
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = server.accept();
                    socketChannel.configureBlocking(false);
                    // 这里只注册了读事件,如果需要给客户端发送数据可以注册写事件
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("客户端连接成功");

                    // 如果是OP_READ事件,则进行读取和打印
                } else if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                    int len = socketChannel.read(byteBuffer);
                    // 如果有数据,把数据打印出来
                    if (len > 0) {
                        System.out.println("接收到消息:" + new String(byteBuffer.array()));

                        // 如果客户端断开连接,关闭Socket
                    } else if (len == -1) {
                        System.out.println("客户端断开连接");
                        socketChannel.close();
                    }
                }
                //从事件集合里删除本次处理的key,防止下次select重复处理
                iterator.remove();
            }
        }
    }
}

流程

image.png

主要概念对比

image.png

NIO模型与交互

java的NIO可以认为是Reactor模式的一个实现,提供了一个编程模型

image.png

NIO核心组件

image.png

NIO 有三大核心组件: Channel(通道), Buffer(缓冲区),Selector(多路复用器) 1、channel 类似于流,每个 channel 对应一个 buffer缓冲区,buffer 底层就是个数组 2、channel 会注册到 selector 上,由 selector 根据 channel 读写等事件的发生将其交由某个空闲的线程处理 3、NIO 的 Buffer 和 channel 都是既可以读也可以写

参照上面的流程,客户端通过buffer与channel交互,Selector通过事件机制与channel进行交互,进而达到客户端与Server的交互通信。

网络通信的编程接口仍旧是Socket,他的实现基础在NIO里面是Channel

image.png

Channel用于源和目的地的连接,是一个双向通道。

而且,必须经过Buffer,不能直接对Channel进行数据的读写,可以查看类图层次,以及对应的read或者write方法的参数得到证明。

小结

NIO就是Java 对Reactor模式的实现,提供了 Buffer、Channel、Selector等核心组件。

通过Channel进行连接操作管理,通过Buffer进行数据读写,通过Selector进行事件绑定回调等。

common_log.png 转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-206-1-1.html

关注下面的标签,发现更多相似文章

文章被以下专栏收录:

    黄小斜学Java

    疯狂的字节X

  • 目前专注于分享Java领域干货,公众号同步更新。原创以及收集整理,把最好的留下。
    包括但不限于JVM、计算机科学、算法、数据库、分布式、Spring全家桶、微服务、高并发、Docker容器、ELK、大数据等相关知识,一起进步,一起成长。
热门推荐
海康摄像头接入 wvp-GB28181-pro平台测试验
[md]### 简介 开箱即用的28181协议视频平台 `https://github.c
[CXX1300] CMake '3.18.1' was not
[md][CXX1300] CMake '3.18.1' was not found in SDK, PATH, or
[若依]微服务springcloud版新建增添加一个
[md]若依框架是一个比较出名的后台管理系统,有多个不同版本。