技术整理分享:nio和netty

https://tieba.baidu.com/p/6082929153?red_tag=2754348730

总结:

 

NIO(Non - blocking I/O)详解

概述

NIO 是 Java 1.4 引入的新 I/O 模型,与传统的阻塞 I/O(BIO)不同,NIO 是基于通道(Channel)和缓冲区(Buffer)进行操作的,并且支持非阻塞通信,能够显著提高程序的并发处理能力和性能。

核心组件及原理

  • 缓冲区(Buffer):是一个用于存储数据的容器,本质上是一个数组,例如 ByteBufferCharBuffer 等。数据可以从通道读取到缓冲区,也可以从缓冲区写入通道。
  • 通道(Channel):可以看作是数据传输的管道,用于连接数据源和数据目的地。常见的通道有 FileChannel(用于文件读写)、SocketChannel(用于网络通信)等。
  • 选择器(Selector):是 NIO 实现非阻塞的关键。一个选择器可以监听多个通道的 I/O 事件(如读、写、连接等),当某个通道有事件发生时,选择器会将其选中,程序可以对这些事件进行处理。

举例说明

以下是一个简单的 NIO 文件读取示例:

import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class NIOFileReadExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("test.txt");
             FileChannel channel = fis.getChannel()) {
            // 创建一个容量为 1024 的 ByteBuffer
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            // 从通道读取数据到缓冲区
            int bytesRead = channel.read(buffer);
            while (bytesRead != -1) {
                // 切换缓冲区为读模式
                buffer.flip();
                while (buffer.hasRemaining()) {
                    System.out.print((char) buffer.get());
                }
                // 清空缓冲区
                buffer.clear();
                bytesRead = channel.read(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,首先创建了一个 FileInputStream 和对应的 FileChannel,然后创建了一个 ByteBuffer 用于存储从文件中读取的数据。通过 channel.read(buffer) 方法将数据从通道读取到缓冲区,再将缓冲区的数据输出。

Netty 详解

概述

Netty 是一个基于 Java NIO 实现的高性能网络编程框架,它简化了网络编程的复杂性,提供了易于使用的 API,同时具有高吞吐量、低延迟等特点,广泛应用于开发网络服务器和客户端程序。

核心组件及原理

  • Channel:Netty 中的通道,类似于 NIO 中的通道,用于网络数据的读写。
  • EventLoop:是 Netty 的事件循环器,负责处理通道的 I/O 事件和任务调度。一个 EventLoop 可以处理多个通道的事件。
  • ChannelPipeline:是一个 ChannelHandler 的链表,每个 ChannelHandler 负责处理特定的业务逻辑,如数据的编解码、业务处理等。当有数据在通道中流动时,会依次经过 ChannelPipeline 中的各个 ChannelHandler

举例说明

以下是一个简单的 Netty 服务器示例:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class NettyServer {
    private final int port;

    public NettyServer(int port) {
        this.port = port;
    }

    public void run() throws Exception {
        // 创建两个 EventLoopGroup,一个用于接受客户端连接,一个用于处理网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
              .channel(NioServerSocketChannel.class)
              .childHandler(new ChannelInitializer<SocketChannel>() {
                  @Override
                  public void initChannel(SocketChannel ch) throws Exception {
                      ch.pipeline().addLast(new StringDecoder());
                      ch.pipeline().addLast(new StringEncoder());
                      ch.pipeline().addLast(new NettyServerHandler());
                  }
              })
              .option(ChannelOption.SO_BACKLOG, 128)
              .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口,开始接收进来的连接
            ChannelFuture f = b.bind(port).sync();

            // 等待服务器  socket 关闭 。
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8080;
        new NettyServer(port).run();
    }
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("Received from client: " + msg);
        ctx.writeAndFlush("Server received: " + msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

在这个例子中,创建了两个 EventLoopGroup,分别用于接受客户端连接和处理网络读写。ServerBootstrap 用于启动服务器,通过 childHandler 方法配置 ChannelPipeline,添加了字符串编解码器和自定义的 NettyServerHandler。当客户端发送消息时,NettyServerHandler 会接收消息并将处理结果返回给客户端。

总结

NIO 是 Java 提供的非阻塞 I/O 模型,为高性能网络编程提供了基础。而 Netty 是基于 NIO 构建的高性能网络编程框架,它简化了 NIO 的使用,让开发者可以更方便地开发网络应用程序。

posted @   皇问天  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示