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();//设置写模式
相关推荐
海上彼尚1 小时前
Go之路 - 7.go的结构体
开发语言·后端·golang
源代码•宸6 小时前
分布式缓存-GO(分布式算法之一致性哈希、缓存对外服务化)
开发语言·经验分享·分布式·后端·算法·缓存·golang
It's now6 小时前
Spring AI 基础开发流程
java·人工智能·后端·spring
计算机毕设VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue图书商城系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
夕颜1118 小时前
BeeAI 框架学习记录
后端
极市平台8 小时前
骁龙大赛-技术分享第5期(上)
人工智能·经验分享·笔记·后端·个人开发
程序员爱钓鱼8 小时前
Node.js 编程实战:路由处理原理与实践
后端·node.js·trae
hhzz9 小时前
Spring Boot整合Activiti的项目中实现抄送功能
java·spring boot·后端
Victor35610 小时前
Netty(7)如何实现基于Netty的TCP客户端和服务器?
后端
Victor35610 小时前
Netty(8)什么是Netty的ChannelPipeline和ChannelHandler?
后端