当发送“Hello,World”时,channel发生了什么?

news2024/11/26 4:19:47

一、Netty概述

1.Netty是什么?

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

2.Netty的地位怎么样?

Netty 在 Java 网络应用框架中的地位就好比:Spring 框架在 JavaEE 开发中的地位

以下的框架都使用了 Netty,因为它们有网络通信需求!

  • Cassandra - nosql 数据库

  • Spark - 大数据分布式计算框架

  • Hadoop - 大数据分布式存储框架

  • RocketMQ - ali 开源的消息队列

  • ElasticSearch - 搜索引擎

  • gRPC - rpc 框架

  • Dubbo - rpc 框架

  • Spring 5.x - flux api 完全抛弃了 tomcat ,使用 netty 作为服务器端

  • Zookeeper - 分布式协调框架

3.Netty有哪些优势?

  • Netty vs NIO,工作量大,bug 多

    • 需要自己构建协议

    • 解决 TCP 传输问题,如粘包、半包

    • epoll 空轮询导致 CPU 100%

    • 对 API 进行增强,使之更易用,如 FastThreadLocal => ThreadLocal,ByteBuf => ByteBuffer

  • Netty vs 其它网络应用框架

    • Mina 由 apache 维护,将来 3.x 版本可能会有较大重构,破坏 API 向下兼容性,Netty 的开发迭代更迅速,API 更简洁、文档更优秀

    • 久经考验,16年,Netty 版本

      • 2.x 2004

      • 3.x 2008

      • 4.x 2013

      • 5.x 已废弃(没有明显的性能提升,维护成本高)

二、使用Netty实现一个简单的网络通信模型

开发一个简单的服务器端和客户端:

客户端向服务器端发送“Hello,World!”;服务器只接收并打印输出,不返回。

加依赖

    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>4.1.39.Final</version>
    </dependency>

服务器端

public class HelloServer {
    public static void main(String[] args) {
        // 1. 启动器,负责组装netty组件,启动服务器
        new ServerBootstrap()
                // 2. BossEventLoop, WorkerEventLoop(selector,thread), group组
                .group(new NioEventLoopGroup())
                // 3. 选择 服务器的 ServerSocketChannel 实现
                .channel(NioServerSocketChannel.class) // OIO BIO
                // 4.boss 负责处理连接 worker(child) 负责处理读写,决定了 worker(child)能执行那些操作(handler)
                .childHandler(
                        // 5. channel 代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的handler
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel ch) throws Exception {
                                // 6. 添加具体的 handler
                                ch.pipeline().addLast(new StringDecoder()); // 将ByteBuf 转换为字符串
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){ // 自定义 handler
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        // 打印上一步转换好的字符串
                                        System.out.println(msg);
                                    }
                                });
                            }
                        }
                )
                // 7.绑定监听端口
                .bind(9090);
    }
}

 代码解读

1.服务器端创建一个新的ServerBootstrap实例。ServerBootstrap是Netty中用于设置服务器端的参数并启动服务器的启动类。

2.为服务器设置一个事件循环组。NioEventLoopGroup是一个基于NIO(非阻塞I/O)的实现,用于处理I/O操作的多线程事件循环。这允许服务器处理多个并发连接。可以理解为创建一个组,组中包含多个eventLoop,把 eventLoop 理解为处理数据的工人:

  • 工人可以管理多个 channel 的 io 操作,并且一旦工人负责了某个 channel,就要负责到底(绑定)。

  • 工人既可以执行 io 操作,也可以进行任务处理,每位工人有任务队列,队列里可以堆放多个 channel 的待处理任务,任务分为普通任务、定时任务。

3.选择一个serverChannel的实现,有基于NIO的服务器端实现、OIO(阻塞IO)的服务器端实现、基于Linux的Epoll的服务器端实现等。

4.添加事件处理逻辑。

5.ChannelInitializer是一个特殊的channel处理器,用于对channel中的handler进行初始化,具体的handler添加到initChannel()方法中。可以把handler 理解为数据的处理工序。

6.数据传输都是以字节形式传输,Netty使用ByteBuf对NIO中ByteBuffer进行增强,通过StringDecode()解码成字符,传输给msg,最终打印输出。pipeline可以理解为把多道工序合在一起, pipeline负责发布事件(读、读取完成...)传播给每个 handler, handler 对自己感兴趣的事件进行处理(重写了相应事件处理方法)

7.绑定端口,用于客户端连接。

 客户端

public class HelloClient {
    public static void main(String[] args) throws InterruptedException {
        // 1. 启动类
        new Bootstrap()
                //  2. 添加EventLoop
                .group(new NioEventLoopGroup())
                // 3. 选择客户端 channel 实现
                .channel(NioSocketChannel.class)
                // 4. 添加处理器
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new StringEncoder());
                    }
                })
                // 5. 连接到服务器
                .connect(new InetSocketAddress("localhost",9090))
                // 6. 等待connect建立连接完毕
                .sync()
                // 7. 获取channel对象
                .channel()
                // 8. 向服务发送数据
                .writeAndFlush("hello, world");
    }
}

代码解读

1.客户端创建一个新的Bootstrap实例。Bootstrap是Netty中用于设置客户端参数并启动客户端的启动类。

2.NioEventLoopGroup,同 Server。

3.选择客户 Socket 实现类,NioSocketChannel 表示基于 NIO 的客户端实现,其它实现还有基于OIO的客户端实现、基于Linux的Epoll的客户端实现等。

4.添加 SocketChannel 的处理器,ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器。

5.指定要连接的服务器和端口。

6.Netty 中很多方法都是异步的,如 connect,这时需要使用 sync 方法等待 connect 建立连接完毕。

7.获取 channel 对象,它即为通道抽象,可以进行数据读写操作。

8.写入消息并清空缓冲区。

运行结果

流程梳理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1287440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5个超实用GPT技巧,包括绩效总结、头脑风暴、营销策略等(内附提示词)

今天和大家分享5个用于工作上的GPT技巧&#xff0c;例如进行绩效总结、自我评估、头脑风暴&#xff0c;还是制作PPT方案等等&#xff0c;最大化提升你工作效率&#xff0c;本期内容对于大家来说都非常受用&#xff0c;记得收藏起来哦&#xff01; 那么接下来就直接进入正题吧&a…

力扣题:字符的统计-12.5

力扣题-12.5 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;551. 学生出勤记录 I 解题思想&#xff1a;进行字符的统计即可 class Solution(object):def checkRecord(self, s):""":type s: str:rtype: bool"""fla…

网工内推 | 上市公司初级网工,HCIP认证优先,14薪,享企业年金

01 易佰网络 招聘岗位&#xff1a;初级网络工程师 职责描述&#xff1a; 1.电脑周边设备&#xff08;打印机、扫描仪、传真机、复印机、投影仪等&#xff09;安装与维护&#xff1b; 2.局域网维护&#xff1b;无线网WLAN维护&#xff1b;监控系统维护&#xff1b; 3.固资维护管…

如何使用 Docker 安装 Node-RED

安装 Node-RED 使用 Docker 是一种简便的方式&#xff0c;以下是基本的步骤&#xff1a; 安装 Docker&#xff1a; 确保已在系统上安装 Docker。可从 Docker 官方网站 或 Windows Docker 安装教程 获取安装指南。 拉取运行 Node-RED 镜像&#xff1a; 打开终端或命令行界面&am…

【MySQL】基本安装配置

1 基础知识 1.1 MySQL安装 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 1.1.1 安装过程 配置环境变量&#xff08;和配置Java8的环境变量如出一辙&#xff09;在MySQL解压文件夹下&#xff0c;导入my.ini文件&#xff0c;与bin目录同级&#xff0c;具体文…

关于inline函数声明和定义为什么不可以分离

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 inline函数在使用时声明和定义不可以分离&#xff0c;接下来我们将会解释为什么是这样的。 我们从程序的编译链接说起。 首先我们先介绍一下程序的翻译环境&#xff1a; 编译分以下几个步骤&#xff0c;预处理&#x…

sort by modulus of a complex number

描述 复数E包含实部x和虚部y, Exyi;E的模为: 输入n(<1000)和n对(x,y); 按模数升序对复合体进行排序&#xff0c;如果模数相等&#xff0c;则按输入顺序排序。 排序后输出n行of (x_i,y_i,mod_i)&#xff0c;保留2个十进制小数。 输入 输入n和n对(x,y); 输出 输出排序后的n行(…

Android : AndroidStudio开发工具优化

1.开启 gradle 单独的守护进程 Windows: 进入目录 C:\Users\Administrator\.gradle 创建文件&#xff1a; gradle.properties # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Settings specified in this file will override any Gradle s…

在python的Scikit-learn库中,可以使用train_test_split函数来划分训练集和测试集。

文章目录 一、在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试集总结 一、在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试集 在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试…

深度观察|近视防控乱象下,角膜塑形镜撬动百亿市场的背后…

前不久&#xff0c;“晒眼皮”莫名上了热搜。顾名思义&#xff0c;就是在太阳底下闭眼&#xff0c;让眼皮享受日光浴。 不少近视患者相信&#xff0c;这种做法可以延缓近视&#xff0c;甚至可以让近视度数“清零”。毫无疑问&#xff0c;这是一个收割智商税的做法&#xff0c;…

数字双胞胎:低代码与工业4.0的崭新融合

引言 随着工业4.0的快速发展&#xff0c;数字化转型已经成为制造业的关键课题。在这个数字化浪潮中&#xff0c;"数字双胞胎"技术崭露头角&#xff0c;它将实际世界与数字模拟相连接&#xff0c;提供了更好的生产过程理解、监控和优化方法。但数字双胞胎的构建和维护…

CoreDNS实战(七)-日志处理

本文主要用于介绍CoreDNS用来记录日志的几种方式以及在生产环境中遇到的一些问题和解决方案。 1 log插件 coredns的日志输出并不如nginx那么完善&#xff08;并不能在配置文件中指定输出的文件目录&#xff0c;但是可以指定日志的格式&#xff09;&#xff0c;默认情况下不论…

算法笔记:样条插值

1 什么是样条 样条来源于早期工程制图&#xff0c;为了将一些固定点连成一条光滑的曲线&#xff0c;采用具有弹性的木条固定在这些点上通过样条画出来的曲线不仅经过各固定点&#xff0c;而且连续光滑 2 样条函数 数学上定义成一个分段多项式函数 每两个点之间用一个多项式来…

手机大厂必备测试技能有哪些?CTS 兼容测试首当其冲

这么多手机厂商都要改造成自己的UI&#xff0c;甚至要对Android底层进行改动&#xff0c;难免不会改出什么问题。 所以Google为了这些定制的系统能够符合统一的规范、兼容Android底层的API&#xff0c;就引入了CTS测试。 01 何为CTS 相信小伙伴们都有用过各种款式的Android手…

CUDA简介——编程模式

1. 引言 前序博客&#xff1a; CUDA简介——基本概念 CPU是用于控制的。即&#xff0c;host控制整个程序流程&#xff1a; 1&#xff09;程序以Host代码main函数开始&#xff0c;然后顺序执行。 Host代码是顺序执行的&#xff0c;并执行在CPU之上。Host代码会负责Launch ke…

解析 Smilee Finance:基于无偿损失的链上期权方案

“有了 Smilee Finance&#xff0c;无偿损失或许不再是一种损失&#xff0c;它也更可能是一种可组合性的收益” 无偿损失 流动性挖矿是引燃 DeFi Summer 的导火索&#xff0c;在 AMM DEX 中&#xff0c;它允许用户将资产按照比例添加到 AMM 流动性池中成为 LP&#xff0c;以为交…

Web漏洞-XSS绕过和pikachu靶场4个场景(三)

★★实战前置声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将其信息做其他用途&#xff0c;由用户承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、XSS漏洞挖掘与绕过 1.1、XSS漏洞挖掘 数据…

Leetcode刷题笔记题解(C++):LCR 021. 删除链表的倒数第 N 个结点

思路&#xff1a;用双指针去遍历链表&#xff0c;删除left的下一个节点&#xff0c;注意的是n大于等于链表长度即删除第一个节点 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {…

设计模式——七大设计原则

设计模式——七大设计原则 1、单一职责原则&#xff08;SRP&#xff09;2、开放封闭原则&#xff08;OCP&#xff09;3、依赖倒转原则&#xff08;DIP&#xff09;4、里氏替换原则 (LSP)5、接口隔离原则 (ISP)6、合成/聚合复用原则 (CARP)7、迪米特法则 (LoD) 了解 设计模式 的…

bootstrap中的图标元素可以免费使用

Available glyphsIncludes over 250 glyphs in font format from the Glyphicon Halflings set. Glyphicon 网址如下&#xff1a; Components Bootstrap