博客
关于我
Netty基础—2.网络编程基础四
阅读量:790 次
发布时间:2023-02-14

本文共 4319 字,大约阅读时间需要 14 分钟。

NIO网络编程实战与Reactor模式

Buffer网络编程

Buffer的作用

Buffer(缓冲区)是NIO中用于高效读写数据的核心组件。它通过将数据从通道读入缓冲区,再从缓冲区写入通道,简化了数据传输过程。应用程序在发送数据时,会先将数据写入缓冲区,然后通过通道发送;在接收数据时,先从通道读取到缓冲区,再逐个读取缓冲区数据。

Buffer的重要属性

  • Capacity(容量)

    Buffer的容量决定了可以存储的最大数据量。只能往Buffer中写入capacity个字节、长整型或字符。一旦Buffer满了,需要通过clear()或compact()方法清空。

  • Position(位置)

    表示当前在缓冲区中可以写入或读取的位置。初始值为0,写入或读取数据后,position会移动到下一个可写入或可读的位置。

  • Limit(限制)

    在写模式下,limit表示缓冲区中可以写入的最大数据量,等于capacity。切换到读模式后,limit表示可以读取的最大数据量。

  • Buffer分配与操作

  • 分配

    使用allocate()方法分配内存,例如:

    ByteBuffer buf = ByteBuffer.allocate(1024);
  • 读写操作

    • 写数据:从通道读取到Buffer,或者直接调用put()方法。
    • 读数据:从Buffer读取到通道,或者调用get()方法。
    • 常用步骤:
    • 写入数据。
    • 调用flip()切换到读模式。
    • 读取数据。
    • 调用clear()或compact()清空缓冲区。
  • 其他操作

    • rewind():将position设回0。
    • clear():清空缓冲区,position设为0,limit设为capacity。
    • compact():将未读数据移动到缓冲区起始位置,position设为最后一个未读数据后面。
  • Selector与Channel

    Selector的作用

    Selector(选择器)用于管理和监听多个通道(Channel)的读写事件。它通过注册事件类型(如OP_READ、OP_WRITE)来判断何时需要处理哪个通道。

    Channel的作用

    Channel是NIO中用于高效读写数据的核心类。常见的Channel实现包括SocketChannel和ServerSocketChannel,它们都继承自SelectableChannel。所有通道都需要通过Buffer进行数据传输。

    SelectionKey

    SelectionKey用于表示对特定通道的操作事件感兴趣。定义了四种事件类型:OP_ACCEPT、OP_READ、OP_WRITE、OP_CONNECT。这些事件类型对应不同的网络操作。

    NIO开发流程

  • 服务端启动

    使用ServerSocketChannel创建服务器,并注册OP_ACCEPT事件处理器。

  • 客户端连接

    客户端通过SocketChannel连接到服务器,并注册OP_CONNECT事件处理器。

  • 数据交互

    • 服务端接收连接后,创建SocketChannel并注册OP_READ事件。
    • 客户端在连接建立后,注册OP_READ事件以便读取数据。
  • IO循环处理

    使用Selector管理多个通道,等待事件就绪。每次循环中,调用select()方法阻塞等待事件,然后处理对应的事件。

  • NIO开发示例

    服务端代码

    public class NioServer {    private static Selector selector;    private static ServerSocketChannel serverChannel;    public static void main(String[] args) {        try {            selector = Selector.open();            serverChannel = ServerSocketChannel.open();            serverChannel.configureBlocking(false);            serverChannel.socket().bind(new InetSocketAddress(8080));            serverChannel.register(selector, SelectionKey.OP_ACCEPT);            startServer();        } catch (IOException e) {            e.printStackTrace();        }    }    private static void startServer() {        while (!Thread.currentThread().isInterrupted()) {            try {                selector.select();                Set
    keys = selector.selectedKeys(); Iterator
    it = keys.iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); if (key.isAcceptable()) { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); } } } catch (IOException e) { e.printStackTrace(); } } }}

    客户端代码

    public class NioClient {    private static Selector selector;    private static SocketChannel socketChannel;    public static void start() {        try {            selector = Selector.open();            socketChannel = SocketChannel.open();            socketChannel.configureBlocking(false);            socketChannel.register(selector, SelectionKey.OP_CONNECT);        } catch (IOException e) {            e.printStackTrace();        }    }    public static void main(String[] args) {        start();        Scanner scanner = new Scanner(System.in);        while (true) {            System.out.println("请输入消息:");            String msg = scanner.nextLine();            if (!sendMsg(msg)) {                break;            }        }    }    private static boolean sendMsg(String msg) {        try {            socketChannel.register(selector, SelectionKey.OP_READ);            ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());            buffer.flip();            int bytesWritten = socketChannel.write(buffer);            return bytesWritten > 0;        } catch (IOException e) {            e.printStackTrace();            return false;        }    }}

    Reactor模式简介

    Reactor模式通过多个Reactor线程管理IO操作,提升了吞吐量和系统性能。其核心思想是将IO事件分散到多个线程,从而避免单线程处理大量IO请求带来的性能瓶颈。

    单线程Reactor模式

  • 流程

    • Reactor线程启动事件循环。
    • 注册Acceptor事件处理器。
    • 处理连接请求和读写事件。
  • 优化

    • 使用线程池处理非IO业务逻辑,提高IO响应速度。
  • 局限性

    • 单线程无法处理高并发场景,性能受限。
  • 多线程Reactor模式

  • 流程

    • MainReactor处理连接请求。
    • SubReactor线程池处理读写事件。
  • 优势

    • 主Reactor负责接收连接,SubReactor负责数据通信。
    • 适用于高并发场景,提升吞吐量。
  • 应用

    • Netty框架常用多线程Reactor模式。
  • 通过以上优化,NIO网络编程实现了高效的数据传输和事件处理,适用于各种网络应用场景。

    转载地址:http://cjcfk.baihongyu.com/

    你可能感兴趣的文章
    Nature | 电子学“超构器件”, 从零基础到精通,收藏这篇就够了!
    查看>>
    Nature和Science同时报道,新疆出土四千年前遗骸完成DNA测序,证实并非移民而是土著...
    查看>>
    Nat、端口映射、内网穿透有什么区别?
    查看>>
    Nat、端口映射、内网穿透有什么区别?
    查看>>
    nat打洞原理和实现
    查看>>
    NAT技术
    查看>>
    NAT模式/路由模式/全路由模式 (转)
    查看>>
    NAT模式下虚拟机centOs和主机ping不通解决方法
    查看>>
    NAT的两种模式SNAT和DNAT,到底有啥区别?
    查看>>
    NAT的全然分析及其UDP穿透的全然解决方式
    查看>>
    NAT类型与NAT模型详解
    查看>>
    NAT网络地址转换配置实战
    查看>>
    NAT网络地址转换配置详解
    查看>>
    navbar navbar-inverse 导航条设置颜色
    查看>>
    Navicat for MySQL 命令列 执行SQL语句 历史日志
    查看>>
    Navicat for MySQL 查看BLOB字段内容
    查看>>
    Navicat for MySQL笔记1
    查看>>
    Navicat for MySQL(Ubuntu)过期解决方法
    查看>>
    Navicat Premium 12 卸载和注册表的删除
    查看>>
    Navicat 导入sql文件
    查看>>