Netty应用开发-之简单介绍Netty以及NIO基本开发

孙哥分布式系列课程 --- Netty应用开发


1. 引言

1.1 什么是Netty

netty.io/

Netty是一个异步事件驱动的网络应用框架。 用于快速开发可维护的高性能协议服务器和客户端。

Netty是一个NIO客户服务器框架,它能够快速和容易地开发网络应用,如协议服务器和客户端。它大大简化和精简了网络编程,如TCP和UDP套接字服务器。

快速和简单 "并不意味着开发出来的应用程序会出现可维护性或性能问题。Netty的设计是经过精心设计的,其经验来自于许多协议的实施,如FTP、SMTP、HTTP以及各种基于二进制和文本的遗留协议。因此,Netty成功地找到了一种方法来实现开发的简易性、性能、稳定性和灵活性,而没有任何妥协。

1.2 为什么要学习Netty
markdown 复制代码
1. Netty已经是行业内网络通信编程的标准,广泛应用于通信领域和很多其他中间件技术的底层。
 
2. 应用非常广泛
   1. 游戏行业
   2. 很多框架的通信底层,解决进程间通信。
      Spring WebFlux、storm、rocketMQ、dubbo等,是分布式系统,通信的核心。

2. NIO编程

markdown 复制代码
1. NIO全称成为None Blocking IO (非阻塞IO)。【JDK1.4】
2. 非阻塞 主要应用在网络通信中,能够合理利用资源,提高系统的并发效率。支持高并发的系统访问。
2.1 传统网络通信中的开发方式及问题
2.1.1 多线程版网络编程

多线程版本的网络编程:

  1. 每次处理请求都要创建一个线程
  2. 内存 占用高,不能无限制创建线程
  3. CPU使用率高
2.1.2 线程池版的网络编程
java 复制代码
//核心线程数(corePoolSize=系统cpu核数,maxinumPollSize :最多创建线程的数量
      // keepAliveTime: 最大等待时长,线程空闲时间超过这个就会销毁,
      // unit : 单位      workQueue: 队列的最大容积
      new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), 20, 120L, TimeUnit.SECONDS, 
              new ArrayBlockingQueue<Runnable>(1000));
           

缺点:客户端请求过来了,建立了连接,但它阻塞了(比如在等客户端输入键盘,)这时候就阻塞了,这使得他这个线程Thread也得等着

2.2 NIO网络通信中的非阻塞编程

服务端还是引入线程池帮我们创建线程: 核心变化:不再使用io进行通信,而是通过管道的方式 Channel NIO帮我们引入了Seletor 服务器 ,可以帮我们监控客户端的Channel是否正常通信(建立连接,没有阻塞) 有着Seletor服务器帮会我们监控,如果一个客户端处于阻塞状态,他会帮我们把他连接的线程给释放出来

3.NIO的基本开发方式

3.1 Channel简介
markdown 复制代码
1. IO通信的通道,类似于InputStream、OutputStream
2. Channel没有方向性
  • 常见Channel

    markdown 复制代码
    1. 文件操作
       FileChannel,读写文件中的数据。
    2. 网络操作
       SocketChannel,通过TCP读写网络中的数据。
       ServerSockectChannel,监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
       DatagramChannel,通过UDP读写网络中的数据。
  • 获得方式

    markdown 复制代码
    1. FileInputStreanm/FileOutputStream
    2. RandomAccessFile
    
    3. Socket
    4. ServerSocket
    5. DatagramSocket
3.2 Buffer简介
markdown 复制代码
1. Channel读取或者写入的数据,都要写到Buffer中,才可以被程序操作。
2. 因为Channel没有方向性,所以Buffer为了区分读写,引入了读模式、写模式进行区分。
  • 常见Buffer

    markdown 复制代码
    1. ByteBuffer
    2. CharBuffer
    3. DoubleBuffer
    4. FloatBuffer
    5. IntBuffer
    6. LongBuffer
    7. ShortBuffer
    8. MappedByteBuffer..
  • 获得方式

    markdown 复制代码
     1. ByteBuffer.allocate(10);
     2. encode()
3.4 第一个NIO程序分析
java 复制代码
 public class TestNIO1 {
    public static void main(String[] args) throws IOException {
        //1 创建Channel通道  FileChannel
        FileChannel channel = new FileInputStream("data.txt").getChannel();

        //2 创建缓冲区
        //1234567890
        ByteBuffer buffer = ByteBuffer.allocate(10);

        while (true) {
            //3把通道内获取的文件数据,写入缓冲区
            int read = channel.read(buffer);

            if (read == -1) break;

            //4.程序读取buffer内容,后续的操作。设置buffer为读模式。
            buffer.flip();

            //5.循环读取缓冲区中的数据
            while (buffer.hasRemaining()) {
                byte b = buffer.get();
                System.out.println("(char)b = " + (char) b);
            }

            //6. 设置buffer的写模式
            buffer.clear();
        }
    }
}


public class TestNIO2 {
    public static void main(String[] args) {
        //RadomAccessFile 异常处理
        FileChannel channel = null;
        try {
            channel = new RandomAccessFile("data.txt", "rw").getChannel();

            ByteBuffer buffer = ByteBuffer.allocate(10);

            while (true) {
                int read = channel.read(buffer);
                if (read == -1) break;

                buffer.flip();
                while (buffer.hasRemaining()) {
                    byte b = buffer.get();
                    System.out.println("(char) b = " + (char) b);
                }

                buffer.clear();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

public class TestNIO3 {
    public static void main(String[] args) {

        try (FileChannel channel = FileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ);) {

            ByteBuffer buffer = ByteBuffer.allocate(10);
            while (true) {
                int read = channel.read(buffer);
                if (read == -1) break;

                buffer.flip();
                while (buffer.hasRemaining()) {
                    byte b = buffer.get();
                    System.out.println("(char)b = " + (char) b);
                }

                buffer.clear();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    } 
}
3.5 NIO开发的步骤总结
markdown 复制代码
1. 获取Channel 
2. 创建Buffer
3. 循环的从Channel中获取数据,读入到Buffer中。进行操作.
    channel.read(buffer);

    buffer.flip();//设置读模式
    循环从buffer中获取数据。
    buffer.get();
    buffer.clear();//设置写模式
相关推荐
小坏讲微服务20 分钟前
SpringCloud零基础学全栈,实战企业级项目完整使用
后端·spring·spring cloud
humors2211 小时前
服务端开发案例(不定期更新)
java·数据库·后端·mysql·mybatis·excel
Easonmax3 小时前
用 Rust 打造可复现的 ASCII 艺术渲染器:从像素到字符的完整工程实践
开发语言·后端·rust
百锦再3 小时前
选择Rust的理由:从内存管理到抛弃抽象
android·java·开发语言·后端·python·rust·go
小羊失眠啦.3 小时前
深入解析Rust的所有权系统:告别空指针和数据竞争
开发语言·后端·rust
q***71854 小时前
Spring Boot 集成 MyBatis 全面讲解
spring boot·后端·mybatis
大象席地抽烟4 小时前
使用 Ollama 本地模型与 Spring AI Alibaba
后端
程序员小假4 小时前
SQL 语句左连接右连接内连接如何使用,区别是什么?
java·后端
小坏讲微服务4 小时前
Spring Cloud Alibaba Gateway 集成 Redis 限流的完整配置
数据库·redis·分布式·后端·spring cloud·架构·gateway
方圆想当图灵5 小时前
Nacos 源码深度畅游:Nacos 配置同步详解(下)
分布式·后端·github