Java笔记之从IO模型到Netty框架学习初识篇

目录
  • 什么是Netty
  • IO模型
  • BIO
    • BIO编程简单流程
    • BIO简单实例
  • NIO
  • Buffer
    • Buffer基本使用
    • Buffer四个主要属性
  • Channel
    • 本地文件写案例
    • 本地文件读案例
    • 本地文件拷贝案例
  • Selector

什么是Netty

  • 异步,基于事件驱动的网络应用框架,用以快速开发高性能,高可靠的网络IO程序
  • 主要针对在TCP协议下,面向Clients端的高并发应用
  • 本质是一个NIO框架,适用于服务器通讯等场景

异步:发送请求无需等待响应,程式接着往下走。

事件驱动:一个连接事件或者断开事件,或者读事件或者写事件,发生后的后续处理。

Netty典型应用:

  • 高性能rpc框架用来远程服务(过程)调用,比如Dubbo。
  • 游戏行业,页面数据交互。
  • 大数据领域如Hadoop高性能通讯和序列化组件(AVRO)。

IO模型

简单理解就是用什么通道去进行数据发送和接收。

BIO:一个连接一个线程,连接不做任何事会造成不必要的线程开销。适用于连接数目较小且固定的架构。

NIO:服务端一个线程(也可以多个),维护一个多路复用器。由多路复用器去处理IO线程。适用于连接数目多且较短的架构

AIO:异步非阻塞,还未得到广泛应用。适用于连接数目多且连接较长的架构。

BIO

BIO编程简单流程

  • 服务端创建启动ServerSocket
  • 客户端启动Socket对服务器进行通信,默认服务器会对每一个客户创建一个线程。
  • 客户端发出请求后,先咨询线程是否有响应,如果没有则等待或者拒绝。
  • 如果有响应,则等待请求结束后,再继续执行。(阻塞)

BIO简单实例

public class BIOserver {
    public static void main(String[] args) throws IOException {
        // 为了方便直接用了Executors创建线程池
        ExecutorService service = Executors.newCachedThreadPool();
        //指定服务端端口
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器启动");
        while(true){
            //阻塞等待连接
            Socket socket = serverSocket.accept();
            System.out.println("连接到一个客户端");
            //每个连接对应一个线程
            service.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        handler(socket);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            });
        }
    }
    public static void handler(Socket socket) throws IOException {
        System.out.println("Thread:"+Thread.currentThread().getId());
        byte[] bytes = new byte[1024];
        InputStream inputStream = socket.getInputStream();
        while (true){
            //阻塞等待读取
            int n = inputStream.read(bytes);
            if(n!=-1){
                System.out.println(new String(bytes,0,n));
            }else {
                break;
            }
        }
        socket.close();
    }
}

测试:使用windows的telnet

使用 ctrl+]

 可以在服务端控制台看到,已经读取到发送的数据

NIO

三大核心部分:Channel(可类比Socket),Buffer,Selector

大概是这个样子。客户端和Buffer交互,Buffer和Channel是一对一的关系。Selector选择操作Channel(事件驱动,如果Channel有事件发生,Selector才去选择操作。)

Buffer

Buffer基本使用

ByteBuffer使用场景较为广泛。

buffer就是一个内存块,所以说nio是面向块/缓冲,底层是数组。数据读写是通过buffer。可以使用方法flip切换读写。

public class BufferNio {
    public static void main(String[] args) {
        //创建buffer容量为5个int
        IntBuffer buffer = IntBuffer.allocate(5);
        //放数据
        buffer.put(1);
        buffer.put(2);
        buffer.put(3);
        buffer.put(4);
        buffer.put(5);
        //读写切换
        buffer.flip();
        //取数据
        //内部维护一个索引,每次get索引都会往后边移动
        while(buffer.hasRemaining()){
            System.out.println(buffer.get());
        }
    }
}

Buffer四个主要属性

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;

mark:标记,很少改变

position:下一个要被读元素的位置,为下次读写做准备

limit:缓冲器当前的终点,不能对缓冲区极限意外的区域读写,可变。

capacity:不可变,创建时指定的最大容量。

上边出现了读写切换的方法flip,我们看下源码,可以看出来通过改变属性实现可读可写的。

    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

可以通过啊更改limit或者position来实现你想要的操作。参数自己决定

        buffer.limit(2);
        buffer.position(1);

Channel

可读可写,上接Selector,下连Buffer。

当客户端连接ServerSocketChannel时,创建客户端自己的SocketChannel。

本地文件写案例

public class ChannelNio {
    public static void main(String[] args) throws IOException {
        String str = "少壮不努力,老大徒伤悲";
        //创建输出流
        FileOutputStream os = new FileOutputStream("D:\\xxxxxxxxxxxxxxxxxxx\\a.txt");
        //获取FileChannel
        FileChannel channel = os.getChannel();
        //创建缓冲
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //把字符串放入缓冲区
        buffer.put(str.getBytes());
        //反转ByteBuffer
        buffer.flip();
        //将ByteBuffer写入到FileChannel
        channel.write(buffer);
        //关闭流
        os.close();
    }
}

图示理解

本地文件读案例

public class ChannelNio {
    public static void main(String[] args) throws IOException {
        FileInputStream is = new FileInputStream("D:\\xxxxxxxxxxxxxxxxxxx\\a.txt");
        FileChannel channel = is.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.read(buffer);
        System.out.println(new String(buffer.array()));
        is.close();
    }
}

本地文件拷贝案例

方法一

public class ChannelNio {
    public static void main(String[] args) throws IOException {
        FileInputStream is = new FileInputStream("D:\\xxxxxxxxxxxxxxxxxxx\\a.txt");
        FileChannel channel = is.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        FileOutputStream os = new FileOutputStream("D:\\xxxxxxxxxxxxxxxxxxx\\b.txt");
        FileChannel osChannel = os.getChannel();
        while (true){
            buffer.clear();
            int i = channel.read(buffer);
            if(i==-1){
                break;
            }
            buffer.flip();
            osChannel.write(buffer);
        }
        is.close();
        os.close();
    }
}

方法二

public class ChannelNio {
    public static void main(String[] args) throws IOException {
        FileInputStream is = new FileInputStream("D:\\xxxxxxxxxxxxxxxxxxx\\HELP.md");
        FileChannel channel = is.getChannel();
        FileOutputStream os = new FileOutputStream("D:\\xxxxxxxxxxxxxxxxxxx\\HELP222.md");
        FileChannel osChannel = os.getChannel();
        osChannel.transferFrom(channel,0,channel.size());
        is.close();
        os.close();
    }
}

Selector

用一个线程处理多个客户端连接。可以检测多个注册通道的事件,并作出相应处理。不用维护所有线程。

Selector可以获得被注册的SocketChannel的一个SelectionKey集合,然后监听select,获得有事件发生的SelectionKey,最后通过SelectionKey获得通道进行相应操作,完成业务。

到此这篇关于Java笔记之从IO模型到Netty框架学习初识篇的文章就介绍到这了,更多相关Java Netty框架内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java搭建简单Netty开发环境入门教程

    下面就是准备Netty的jar包了,如果你会maven的话自然是使用maven最为方便了.只需要在pom文件中导入以下几行 <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1

  • Java基于Netty实现Http server的实战

    目录 HTTP协议基础知识 Netty的http协议栈 基于Netty实现httpserver HTTP协议基础知识 HTTP(超文本传输协议,英文:HyperText Transfer Protocol,缩写:HTTP)是基于TCP/IP协议的应用层的协议,常用于分布式.协作式和超媒体信息系统的应用层协议. http协议的主要特点:(1)支持CS(客户端/服务器)模式.(2)使用简单,指定URL并携带必要的参数即可.(3)灵活.传输非常多类型的数据对象,通过Content-Type指定即可.(

  • Java Netty HTTP服务实现过程解析

    超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议. 在后端开发中接触HTTP协议的比较多,目前大部分都是基于Servlet容器实现的Http服务,往往有一些核心子系统对性能的要求非常高,这个时候我们可以考虑采用NIO的网络模型来实现HTTP服务,以此提高性能和吞吐量,Netty除了开发网络应用非常方便,还内置了HTTP相关的编解码器,让用户可以很方便的开发出高性能的HTTP协议的服务,Spring Webflux默认是使用的N

  • Java NIO框架Netty简单使用的示例

    之前写了一篇文章:Java 网络IO编程总结(BIO.NIO.AIO均含完整实例代码),介绍了如何使用Java原生IO支持进行网络编程,本文介绍一种更为简单的方式,即Java NIO框架. Netty是业界最流行的NIO框架之一,具有良好的健壮性.功能.性能.可定制性和可扩展性.同时,它提供的十分简单的API,大大简化了我们的网络编程. 同Java IO介绍的文章一样,本文所展示的例子,实现了一个相同的功能. 1.服务端 Server: package com.anxpp.io.calculat

  • JAVA Netty实现聊天室+私聊功能的示例代码

    功能介绍 使用Netty框架实现聊天室功能,服务器可监控客户端上下限状态,消息转发.同时实现了点对点私聊功能.技术点我都在代码中做了备注,这里不再重复写了.希望能给想学习netty的同学一点参考. 服务器代码 服务器入口代码 package nio.test.netty.groupChat; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.chann

  • Java游戏服务器系列之Netty相关知识总结

    一.简介 Java的底层API逐渐复杂,而开发者面对的开发场景需求也在逐渐增大.如果直接针对底层API进行编程,无疑是耗时耗力的.这时就催生了极多的编程框架,这些框架隐藏了API实现的复杂细节,以最简洁的方式给开发人员提供功能的实现接口.Netty就是一款针对于网络链接的框架,他的出现让服务器开发人员更加的集中关注于更多逻辑的实现,而不为了实现更好更多更稳定的链接而头疼.Netty的核心功能基于NIO实现. 二.Netty的应用场景 几乎适用于所有的长短链接场景,由于Java应用的广泛性,几乎所

  • Java笔记之从IO模型到Netty框架学习初识篇

    目录 什么是Netty IO模型 BIO BIO编程简单流程 BIO简单实例 NIO Buffer Buffer基本使用 Buffer四个主要属性 Channel 本地文件写案例 本地文件读案例 本地文件拷贝案例 Selector 什么是Netty 异步,基于事件驱动的网络应用框架,用以快速开发高性能,高可靠的网络IO程序 主要针对在TCP协议下,面向Clients端的高并发应用 本质是一个NIO框架,适用于服务器通讯等场景 异步:发送请求无需等待响应,程式接着往下走. 事件驱动:一个连接事件或

  • Java网络编程之IO模型阻塞与非阻塞简要分析

    目录 1.阻塞I/O模型 2.非阻塞I/O模型 1.阻塞I/O模型 阻塞IO模型是常见的IO模型,在读写数据时客户端会发生阻塞.阻塞IO模型的工作流程为: 1.1在用户线程发出IO请求之后,内核会检查数据是否就绪,此时用户线程一直阻塞等待内存数据就绪: 1.2在内存数据就绪后,内核将数据复制到用户线程中,并返回I/O执行结果到用户线程,此时用户线程将解除阻塞状态并开始处理数据. 典型的阻塞I/O模型的例子为data= socket.read(),如果内核数据没有就绪, Socket线程就会一直阻

  • Java NIO:浅析IO模型_动力节点Java学院整理

    也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗.在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型.下面本文先从同步和异步的概念 说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,最后介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor). 以下是本文的目录大纲: 一.什么是同步?什么是异步? 二.什么是阻塞?什么是非阻塞

  • Java框架解说之BIO NIO AIO不同IO模型演进之路

    目录 引言 IO模型 1.什么是IO 2.应用程序IO交互 (1)计算机资源统一管理 (2)底层硬件调用统一封装 3.5种IO模型 (1)阻塞型IO (2)非阻塞型IO (3)多路复用IO (4)信号驱动IO (5)异步IO Java中的IO模型 BIO NIO AIO 总结 引言 Netty作为高性能的网络通信框架,它是IO模型演变过程中的产物.Netty以Java NIO为基础,是一种基于异步事件驱动的网络通信应用框架,Netty用以快速开发高性能.高可靠的网络服务器和客户端程序,很多开源框

  • Java三种IO模型原理实例详解

    Java中IO的模型分为三种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. BIO[同步阻塞] 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程相应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行. NIO[同步非阻塞] NIO本身是基于事

  • Java 中的io模型详解

    1. BIO 我们先看一个 Java 例子: package cn.bridgeli.demo;   import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket;   /**  * @author bridgel

  • Java非阻塞I/O模型之NIO相关知识总结

    组件说明 (1)Channel:NIO模型中的管道,管道是链接建立和通信的重要组件,我们可以理解管道是一个容器环境,我们所有的I/O的建立读取都可以在这个容器中进行 (2)Selector:NIO中的选择器,NIO是由事件驱动的,当有链接事件或者读取事件发生时,这个事件可以注册到这个选择器上,并且最终被我们检测到. (3)SelectionKey:我们可以在Selector中进行检测是否有SelectionKey产生,并且根据这个SelectionKey中的信息判断时什么事件发生了. 代码说明

  • Java使用NIO优化IO实现文件上传下载功能

    目录 1 NIO的一些基础预备知识 2 NIO为何较传统的io速度较快 3 NIO实战上传下载 3.1 url下载文件 3.2 通过NIO上传文件 1 NIO的一些基础预备知识 Java中IO流类的体系中BIO与NIO:https://blog.csdn.net/ZGL_cyy/article/details/104326458Java IO体系与NIO和BIO体系面试题 :https://blog.csdn.net/ZGL_cyy/article/details/122836368为什么使用N

  • Java探索之Thread+IO文件的加密解密代码实例

    这篇文章向大家分享了几段代码,主要是关于Thread+IO文件的加密解密,下面看看具体代码: 加密启动线程 package com.hz.subsection; import java.io.File; public class enCodeFileThread extends Thread { public Files files; public File file; public File dst; public enCodeFileThread(String name,Files file

  • Linux 下的五种 IO 模型详细介绍

    概念说明 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限.为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间.针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空

随机推荐