网络编程-Netty-01 Nio

netty学习笔记-01 netty学习笔记 阅读详情

1、IO模型

目前IO模型实际指数据进行收发的通道模型,常见磁盘IO、网络IO等,是互联网发展到现在各架构体系中最常讨论的话题之一。因为IO的瓶颈限制尝尝导致开发者们不得不通过扩容来解决,而好的IO模型无疑能减少因IO瓶颈而造成的资源浪费。

JAVA目前支持的3中网络变成IO模型:BIO、NIO、AIO

2、BIO(blocking io)

2.1 BIO介绍

同步或异步阻塞式收发模型,客户端的请求需要服务端线程等待处理。

  • 同步阻塞模型:则现成阻塞其他客户端的连接,直至完成当前连接的accept()连接事件或read()读写事件。
  • 异步阻塞模型:常见于在服务端开启线程池,主线程用于接收客户端的accept()连接事件,再有线程池处理客户端的读写事件。但当客户端连接过多,或长连接过多时,服务端仍无法满足非阻塞的需求,而只能让溢出的连接保持阻塞等待,直至超时或中断放弃连接。
    在这里插入图片描述
    在这里插入图片描述
2.2 源码使用demo
//BIO客户端Demo
public class BioSocketClient {
    public static void main(String[] args) throws IOException {
        Socket client = new Socket("127.0.0.1",9090);
        client.getOutputStream().write("hello".getBytes(StandardCharsets.UTF_8));
        client.getOutputStream().flush();
        System.out.println("向服务端发送数据");
        byte[] bytes = new byte[1024];
        //接收服务端的响应
        client.getInputStream().read(bytes);
        System.out.println("接收服务端数据:"+ new String(bytes));
        client.close();
    }
}

//服务端阻塞等待连接
public class BioSocketServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9090);
        while (true){
            System.out.println("等待客户端连接...");
            //accept 阻塞方法
            Socket client = serverSocket.accept();
            System.out.println("有客户端完成连接");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        handleRequest(client);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
	//服务端阻塞等到客户端的读事件
    public static void handleRequest(Socket socket) throws IOException {
        byte[] bytes = new byte[1024];
        System.out.println("阻塞读取客户端消息");
        //read 阻塞方法,接受客户端发送的数据
        int read = socket.getInputStream().read(bytes);
        System.out.println("read数据完成");
        if(read != -1){
            System.out.println("客户端消息:"+ new String(bytes,0,read));
        }
        //处理服务器的响应
        socket.getOutputStream().write("hello client".getBytes(StandardCharsets.UTF_8));
        socket.getOutputStream().flush();
    }
}
2.3 BIO优缺点及应用场景分析
2.3.1 缺点
  • accept()、read()都是阻塞操作,在连接后不做读写会导致线程资源阻塞浪费
  • 当需要更多的连接时,线程数、内存都要飙升,服务端压力很大,常见client10000的C10k问题
2.3.2 使用场景

BIO适用于连接数少且连接稳定的场景,对服务器的压力小

3、NIO

3.1 NIO介绍

NIO被称为Non Blocking io 或new io。可以实现非阻塞式请求,通过将客户端发送的连接注册到多路复用器(selector),保证一个线程可以处理多个连接的连接及读写事件。

3.2 NIO线程模型

在这里插入图片描述
在这里插入图片描述
应用:目前的nio已被广泛应用,技术路线可见
Nio —> Netty —> vert等等,在产品应用中也非常广泛。

3.2 Nio-client/server module

在上图Nio异步非阻塞模型中引入了多个概念,SocketChannel(通道)、ServerSocketChannel、Selector(多路复用器)、SelectorKeys、Buffer(缓冲区)等,我们先行使用基本功能,构建简单的客户端、服务端交互代码,随后对其概念及源码做剖析。
客户端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class NioClient {
    //通道管理器-> 多通道复用
    private Selector selector;

    public static void main(String[] args) throws IOException {
        NioClient nioClient = new NioClient();
        nioClient.initClient();//初始化建立连接
        nioClient.connect();//连接后读和发送消息
    }

    public void initClient() throws IOException {
        SocketChannel channel = SocketChannel.open();
        //channel通道设置为非阻塞式
        channel.configureBlocking(false);

        this.selector = Selector.open();
        //配置服务器地址
        channel.connect(new InetSocketAddress("127.0.0.1",9090));
        //将通道管理和通道绑定,并且监听连接事件
        channel.register(selector, SelectionKey.OP_CONNECT);
    }

    /**
     * 监听建连事件,发生交互
     */
    public void connect() throws IOException {
        while (true){
            //非阻塞式等待事件驱动
            selector.select();

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey key = (SelectionKey) iterator.next();
                iterator.remove();
                //连接事件 -> 发送消息给客户端
                if (key.isConnectable()){
                    SocketChannel channel1 = (SocketChannel) key.channel();
                    //事件监听结果为正在连接,设置为连接完成
                    if (channel1.isConnectionPending()){
                        channel1.finishConnect();
                    }
                    channel1.configureBlocking(false);
                    ByteBuffer buffer = ByteBuffer.wrap("hello server".getBytes(StandardCharsets.UTF_8));
                    channel1.write(buffer);
                    //客户端与服务器建立连接后,监听读写事件
                    channel1.register(selector,SelectionKey.OP_READ);
                }else if (key.isReadable()){
                    //读事件 -> 接收服务器响应内容
                    SocketChannel channel = (SocketChannel) key.channel();
                    //创建读取的缓冲区
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int read = channel.read(buffer);
                    if (read != -1){
                        System.out.println("客户端接受消息:"+ new String(buffer.array()));
                    }
                }
            }

        }
    }
}

服务端:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NioSelectorServer {
    public static void main(String[] args) throws IOException {
        //创建Nio channel
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.socket().bind(new InetSocketAddress(9090));
        //将服务侧channel设置为非阻塞式
        serverSocket.configureBlocking(false);
        //打开Selector 处理channel
        Selector selector = Selector.open();
        //将channel注册到Selector上,并由selector监听accept()事件
        SelectionKey selectionKey = serverSocket.register(selector,SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动并监听accept事件成功");
        while (true){
            //阻塞等待需要处理的事件
            selector.select();

            // 获取selector中注册的全部事件 selectionKey实例
            Set<SelectionKey> selectionKeySet = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeySet.iterator();

            //遍历KeySet对事件进行处理
            while (iterator.hasNext()){
                SelectionKey next = iterator.next();
                //监听到发生了OP_ACCEPT事件
                if (next.isAcceptable()) {
                    ServerSocketChannel channel = (ServerSocketChannel) next.channel();
                    SocketChannel accepted = channel.accept();
                    //设置非阻塞式读事件监听
                    accepted.configureBlocking(false);
                    accepted.register(selector,SelectionKey.OP_READ);
                    System.out.println("客户端连接成功");
                }else if (next.isReadable()){
                    SocketChannel channel = (SocketChannel) next.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                    int read = channel.read(byteBuffer);
                    //有数据则读取并打印
                    if (read > 0){
                        System.out.println("接收数据:"+new String(byteBuffer.array()));
                    }else if (read == -1){
                        System.out.println("客户端断开连接");
                        channel.close();
                    }
                }
                //完成连接事件或读时间  从select中移除
                iterator.remove();
            }
        }
    }
}
3.4 Nio及EPoll源码解析

在这里插入图片描述

3.4.1 JVM跨平台特性

针对不同操作系统,hotspot源码分别不同的类进行处理,得以实现jvm跨平台的能力。如图DefaultSelectorProvider在Windows、macosx、solaris(SunOS、Linux)等有不同的实现。
在这里插入图片描述

3.4.2 核心代码

Selector.open() //创建多路复用器

socketChannel.register() //将channel注册到多路复用器上

selector.select() //阻塞等待需要处理的事件发生

  • SocketChannel 通道,java调用linux内核函数,创建客户端或服务端在linux系统中的socket文件描述器fd。
  • Selector 多路复用器,实际是用于封装linux系统epoll文件描述器的java对象。
  • 将获取到的Socket连接的文件描述符的事件绑定到Selector对应的Epoll文件描述符上,进行事件的异步通知
3.4.3 linux内核函数

linux内核的epoll_create(256)函数
在这里插入图片描述
linux内核的epoll_ctl()函数。linux内核将监听新的fd(socket)的ADD、MODIFY、DELETE事件
在这里插入图片描述
linux内核的epoll_wait()函数。linux内核查询epoll的就绪列表rdlist,等待事件发生。
在这里插入图片描述

从一次SocketException排查,聊聊BIO、NIO和Netty在处理连接关闭时的差异 本文通过分析`java.net.SocketException`异常,深入探讨了BIO、NIO和Netty在处理连接关闭时的机制差异。从BIO的同步阻塞困境到NIO的非阻塞革新,再到Netty的异步事件驱动模型,详细解析了各模型的优缺点及适用场景,为网络编程中的连接管理提供了实用建议。 阅读详情

相关推荐

STM32按键中断切换红绿蓝灯

通过以上步骤,我们实现了使用STM32的按键中断来切换红绿蓝LED灯的功能。在实际应用中,可能还需要考虑更多的细节,如按键消抖、更精确的延时实现等。但上述代码提供了一个基本的框架和思路,可以根据具体需求进行扩展和优化。希望这篇博客对您有所帮助!

2301_79865940的博客 952

RPC框架设计(二)-NIO编程

2.NIO编程 2.1 NIO介绍 Java NIO全称java non-blocking IO,是指JDK提供的新API。从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,被统称为NIO(即 New IO),是同步非阻塞的。 1.NIO有三大核心部分:Channel(通道)、Buffer(缓冲区)、Selector(选择器) 2.NIO是面向缓冲区编程的。数据读取到一个缓冲区中,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞时的高伸缩性风格 3.Java N

路人贾的博客 396

FT2232HL JTAG下载器硬件设计指南:从引脚配置到电平转换实战

本文详细解析了FT2232HL JTAG下载器的硬件设计要点,包括引脚配置、电平转换电路设计及EEPROM配置技巧。通过实战案例展示如何利用FT2232HL实现高速JTAG通信,解决电平不匹配等常见问题,提升嵌入式开发效率。特别适合需要灵活JTAG接口的硬件工程师参考。

weixin_29194693的博客 255

NIO编程

NIO(New I/O)是Java中一种提供了非阻塞式I/O操作的编程模型。它引入了一组新的Java类,用于取代传统的Java I/O类(如InputStream和OutputStream),以提供更高效、更灵活的I/O操作。// 部分NIO API实际上是阻塞的,例如File APIJava NIO允许执行非阻塞的IO。例如,线程可以请求通道将数据读入缓冲区。当通道将数据读入缓冲区时,线程可以做其他事情。一旦数据被读入缓冲区,线程就可以继续处理它。将数据写入通道也是如此。

swadian2008的博客 1681

5分钟搞定Unity+Visual Studio开发环境配置(含C#游戏开发工作负载)

本文提供了一份详细的Unity与Visual Studio开发环境配置指南,帮助开发者在5分钟内完成C#游戏开发工作负载的设置。从Unity Hub安装到Visual Studio关键组件选择,再到常见问题排查,全面覆盖环境搭建的各个环节,显著提升游戏开发效率。

weixin_29014237的博客 248

BEVFormer详解

BEVFormer 是将Transformer架构的自注意机制与BEV视图中3D检测结合起来的一种纯视觉目标检测方案。对于纯视觉的BEV检测方案,其中的重中之重就是如何将2D的图像特征映射到3D空间的BEV栅格,既然是映射关系,那就有前行投影和反向查询两种机制。前向投影是基于深度估计的方法,参考基于深度估计的BEV视图转换方法,典型代表为LSS。反向查询方法思路为先将BEV栅格在Z方向上进行lift提升,然后再映射到图像特征图上进行特征查询。BEVFormer 就是基于这种机制进行2D图像特征到3D空间的B

MAX的专栏 4745

NIO编程简介

NIO(同步非阻塞)

weixin_42386438的博客 970

NVIDIA NCCL 源码解析:从XML拓扑到高性能通信图的构建

本文深入解析了NVIDIA NCCL如何将XML硬件拓扑文件转化为高性能通信图的核心过程。详细阐述了从创建CPU、GPU、NIC等节点,到建立PCIe、NVLink连接,再到计算链路带宽并进行关键排序的完整建图流程。该图是NCCL实现最优通信路径规划、充分发挥NVLink等高速互联性能的基石,直接影响分布式深度学习训练的效率。

convnet3designer的博客 307

java网络编程——NIO架构

简单叙述java NIO架构,并基于NIO架构下实现聊天系统的代码编写

tang_seven的博客 3000

# 执行 DISM 命令时出错 87 未在此上下文中识别出 restorehealth 选项。解决方法

# 执行 DISM 命令时出错 87 未在此上下文中识别出 restorehealth 选项。解决方法

段子手168的博客 1万+

OpenCASCADE:写IGES

OpenCASCADE:写IGES程序涵盖的领域流程说明初始化过程设置翻译参数执行 Open CASCADE Technology 形状转换编写 IGES 文件将开放级联技术形状映射到 IGES 实体曲线表面拓扑实体——人脸模式下的平移公差管理在 IGES 文件中设置分辨率代码架构调用图例子 程序 您可以通过以下步骤将 OCCT 形状转换为 IGES 实体: 初始化进程。 设置翻译参数, 执行模型翻译, 写入输出 IGES 文件。 您可以在写入文件之前转换多个形状。每个形状都将是 IGES 模型中的根实体。

希望我的博客,能帮上你解决学习中工作中所遇到的问题 923

【Netty源码解读和权威指南】第01篇:Netty是什么——从NIO地狱到网络编程天堂的蜕变

摘要 Netty是解决Java NIO开发痛点的异步事件驱动框架,现已成为Dubbo、Flink等顶级开源项目的网络通信基石。本文从Java NIO的开发困境切入,剖析Netty的诞生背景、核心设计哲学(异步事件驱动、零拷贝、内存池化等),并与Mina、Grizzly框架进行对比。最后通过Netty在Dubbo、Flink等主流框架中的应用案例,展现其作为Java生态网络通信事实标准的地位。为开发者提供从"什么是Netty"到"为什么用Netty"的完整认知路径。

xyghehehehe的专栏 257

EMS案例:BMS传导发射超标整改案例

BMS作为新能源汽车的关键部件,其EMC性能直接影响整车的安全性和可靠性。本文通过一个实际的传导发射整改案例,详细展示了从问题定位、分析到解决方案实施的全过程。希望这些经验能够为从事类似产品设计的工程师提供有价值的参考,在未来的产品开发中避免类似问题,设计出更加可靠、稳定的BMS产品。EMC设计是一门结合理论与实践的艺术,只有通过不断积累经验、深入理解电磁场理论,并紧密结合实际应用场景,才能在复杂的电磁环境中设计出鲁棒性强的电子产品。

m0_56451176的博客 272

Netty01NIO

NIO :non-blocking io 非阻塞 IO。

Sky_小天 1171

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Netty01 NIO基础

*注意:内容来源bilibili视频讲义:视频链接non-blocking io 非阻塞 IOchannel 有一点类似于 stream,它就是读写数据的双向通道,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前的 stream 要么是输入,要么是输出,channel 比 stream 更为底层channelbuffer 常见的 Channel 有buffer 则用来缓冲读写数据,常见的 buffer 有selector 单从字面意思不好理解,需要

不爱吃奶昔(zsl0)的博客 196

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Netty教程01:BIO and NIO

1、什么是netty Netty 是由 JBOSS 提供的一个 Java 开源框架,现为 Github上的独立项目。 Netty 是一个异步的、基于事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络 IO 程序。 Netty主要针对在TCP协议下,面向Clients端的高并发应用,或者Peer-to-Peer场景下的大量数据持续传输的应用。 Netty本质是一个NIO框架,适用于服务器通讯相关的多种应用场景 要透彻理解Netty , 需要先学习 NIO , Netty的底层实现是NIO 2、Ne

weixin_40964170的博客 305

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【Netty】学习笔记-01【NIO基础】

Nteey学习笔记,服务自己,方便他人。

weixin_44768683的博客 1195

Netty01-nio

non-blocking io 非阻塞 IOchannel 有一点类似于 stream,它就是读写数据的双向通道,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前的 stream 要么是输入,要么是输出,channel 比 stream 更为底层channelbuffer 常见的 Channel 有buffer 则用来缓冲读写数据,常见的 buffer 有selector 单从字面意思不好理解,需要结合服务器的设计演化来理解它的用途socket1t

学过的东西,讲不出来等于没学。 730

架构师进阶之NIO以及Netty

NIO 在讲解Netty之前,我们先复习一下基础,什么是NIO?网上很多文章,枯燥的讲解了什么是NIO,大家也看的一头雾水,下面我简单而不简洁的给大家解释一下NIO。 首先我们要明白一点,什么时候用多线程?多线程不是适用于所有场景,一般适用于cpu密集型任务。然后比如redis,netty,nginx这些框架的应用场景明显都是IO密集型任务。所以多线程不是适用。举个例子,看看IO密集型场景的瓶...

Just Do It! 940

Java网络编程Netty系列-01 基础原理与应用场景

Netty是一款基于Java的高性能异步网络框架,广泛应用于互联网、游戏、大数据等领域。它采用事件驱动模型,支持高并发网络通信,是构建RPC框架和分布式系统的理想选择。文章详细对比了Java BIO(同步阻塞)、NIO(同步非阻塞)和AIO(异步非阻塞)三种IO模型的特点与适用场景,并通过代码示例演示了BIO的线程池实现。NIO通过多路复用技术显著提升了系统性能,而Netty正是基于NIO构建,能有效解决传统BIO的线程资源浪费问题,适用于需要处理大量短连接的场景。

yangwei2048的博客 675

开发知识点-Java网络编程-Netty

eg:16h 同时跑 16线程 其他 等待(记录保存 )客户端 建立连接 Socket 读写操作 新的线程。应用程序 — 文件 — 网络 之间的 桥梁。阻塞 非阻塞 同步 异步 多路复用。可以处理 多客户端的 操作 但 有限制。可以 设置 容量 capacity 字节。buffer get 无参 读 一个 字节。指针位置 索引下标 position。数据库 消息队列 二进制框架。guava 工具类 合集。logback 日志打印。

aming小老弟 1739

01-netty概览

1 netty基础备忘 1.1 什么是netty? netty是一个非阻塞i/o客户端-服务器框架,主要用于开发java网络应用程序,入协议服务器和客户端.异步事件驱动的网络应用程序框架和工具用于简化网络编程,例如TCP和UDP套接字服务器.Netty最初由JBoss开发,现在由Netty项目社区开发和维护。 * Better throughput, lower latency * less re...

729

Netty_01 NIO编程

Java BIO就是传统的Java I/O编程,其相关的类和接口在java.io。:同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器)。【后有应用实例】BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,程序简单易理解。Java NIO全称,是指JDK提供的新API。从JDK1.4开始,

weixin_57180385的博客 197

『玩转 Netty』NIO 网络模型

文章目录二、NIO 模型2.1 介绍2.2 工作机制2.3 NIO 三大核心原理2.4 Buffer 使用2.5 Channel 案例2.6 Selector(多路复用器)2.7 NIO 与 BIO 比较2.8 NIO 案例2.9 NIO 零拷贝 二、NIO 模型 2.1 介绍 NIO 包括三大核心 [Channel,Buffer,Selector]。面向缓冲区、块编程,数据读入缓存区,需要时在缓冲区中移动,增加处理灵活性,是同步非阻塞的高伸缩性网络。 2.2 工作机制 1、一个线程从通道发送请求或读取数据

方糖世界 1638
上一篇: 服务化-mysql-07 实战分析mysql慢查询
下一篇: 网络编程-Netty-02 Netty核心功能及线程模型
旧梦昂志
博客等级 码龄7年 3724粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧梦昂志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值