文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Netty的介绍与简单使用

2024-12-03 02:37

关注

一、Netty的优势

尽管我们前面学习NIO的时候,我已经尽可能的简化代码,但是我们依旧会发现,JDK NIO的开发依旧是极为复杂,在业务开发中我们还要考虑到业务的处理流程、业务的复用、请求的并发量、请求过程中的编解码问题、网络传输中的半包粘包问题等等,会进一步增加NIO开发的难度!

二、Netty的架构设计

这是来自官网的一张架构图,我们可以大致的了解Netty的模块!

三、Netty的基本使用和介绍

经过上面的介绍,我们大概了解了Netty的基本架构,下面我们会看一下Netty的基本使用,然后我会逐行解析,希望能够通过这一节课帮助大家入门Netty编程,也为后面的源码学习更好的铺垫一下!

1. 开发一个服务端

我们使用Netty开发一个简单的服务端代码:

服务端接收到客户端的消息,打印出来,然后主动中断连接!

启动服务端源代码:

  1.  
  2. public class EchoServerHandler extends ChannelInboundHandlerAdapter { 
  3.     @Override 
  4.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
  5.         ByteBuf byteBuf = (ByteBuf) msg; 
  6.         try { 
  7.             //转换为字符串 
  8.             String message = byteBuf.toString(StandardCharsets.UTF_8); 
  9.             System.out.println(message); 
  10.         }finally { 
  11.             ReferenceCountUtil.release(byteBuf); 
  12.             ctx.channel().close(); 
  13.         } 
  14.     } 

2. 服务端源代码介绍

  1. EventLoopGroup boss = new NioEventLoopGroup(1); 
  2. EventLoopGroup worker = new NioEventLoopGroup(); 

定义两个事件循环组,还记得我们第五章将的我们对NIO的优化版本吗?现在暂时你可以把它理解为两个selector组:

boss接收到新连接后,将新连接产生的SocketChannel交给worker线程组处理!用一个现在比较流行的比喻:boss相当于老板,worker相当于工人,boss不处理工作,只负责在外面跑业务拉活谈合同。接到新活之后,就把这个活交给worker来干,自己再去接下一个活!

这两行代码建议参考上一章的NIO的优化版本学习!

  1. ServerBootstrap serverBootstrap = new ServerBootstrap(); 

ServerBootstrap是Netty为我们提供的一个快速启动配置类,为什么Netty相较于NIO开发比较简单,就是因为Netty为我们提供了一个网络编程的代码的模板,那么想要使用这些模板,就必须要告诉模板一些必要的参数,供模板读取,而ServerBootstrap正式这个作用,通过初始化的时候,我们设置各种参数,我们将之保存到ServerBootstrap中,后续Netty服务启动的时候,会读取我们初始化的时候配置的各种参数,完成自己的初始化!

  1. serverBootstrap.group(boss, worker) 

将我们前面初始化的两个事件循环组绑定起来,保存到serverBootstrap中,供后续读取!

  1. .channel(NioServerSocketChannel.class) 

我们这里开发的是一个服务端程序,所以我们使用的是NioServerSocketChannel,在Netty中分为两种SocketChannel,一种是NioServerSocketChannel一种是NioSocketChannel,两者都继承与JDK的ServerSocketChannel和SocketChannel,是Netty官方对于通讯管道的扩展:

有关于两个通道,我们后面会详细分析,这里你们先记着,NioServerSocketChannel代表着服务端通道!NioSocketChannel代表着客户端通道,不要搞混了!

  1. .localAddress(8989) 

设置一个端口号,服务端对外暴露的端口号!

  1. .childHandler(new ChannelInitializer() { 
  2.     @Override 
  3.     protected void initChannel(SocketChannel socketChannel) throws Exception { 
  4.         socketChannel.pipeline().addLast(new EchoServerHandler()); 
  5.     } 
  6. }); 

这个代码及其重要,后面也会重点提及,这里主要是做服务编排的,想客户端Socket绑定一个通道,并添加我们的业务处理类 xxxxHandler,当一个客户端连接上服务端后,后续所有的业务处理,都会由这里注册的各种Handler来处理,这就是Netty提供的能够让开发人员专注于业务开发的主要逻辑所在,后面会对这一块代码进行一个重点的讲解,这里也只需要记住,我们注册这些Handler后,客户端发来的数据都会在这些Handler中流转处理!

  1. ChannelFuture channelFuture = serverBootstrap.bind().sync(); 

上面的初始化完成了,开始进行服务器启动和端口绑定,根据上面设置的端口号绑定,细心的同学可能会发现我还调用了一个sync方法,Netty是基于异步事件来开发的,这里我们进行bind调用之后,因为是异步执行,所以我们并不知道什么时候完成,所以这里调用了一个阻塞的方法(sync),一直阻塞等待绑定完成后才继续往下走!

  1. channelFuture.channel().closeFuture().sync(); 

获取一个服务端的通道对象,并且对服务端的通道对象添加一个关闭的监听,并调用阻塞方法(sync),调用后,程序会一直阻塞再这里,等待服务端管道关闭,才会继续往下走!一般来说,服务端管道除非我们主动停机活因为异常崩溃,否则服务端管道会一直存活,那么改程序将会一直阻塞在这里,形成一个服务!

  1. boss.shutdownGracefully(); 
  2. worker.shutdownGracefully(); 

优雅停机,该段程序会将通道标记为不可用状态,等待程序处理完毕后,释放Netty所创建的所有资源!

  1. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {....} 

当服务端察觉到客户端发来数据时,回调该逻辑!

3. 开发一个客户端

  1.  
  2. public class EchoClient { 
  3.     public static void main(String[] args) { 
  4.         EventLoopGroup worker = new NioEventLoopGroup(); 
  5.  
  6.         try { 
  7.             Bootstrap bootstrap = new Bootstrap(); 
  8.             bootstrap.remoteAddress("127.0.0.1", 8989) 
  9.                     .group(worker) 
  10.                     .channel(NioSocketChannel.class) 
  11.                     .handler(new ChannelInitializer() { 
  12.                         @Override 
  13.                         protected void initChannel(SocketChannel ch) throws Exception { 
  14.                             ch.pipeline().addLast(new EchoClientHandler()); 
  15.                         } 
  16.                     }); 
  17.  
  18.             ChannelFuture channelFuture = bootstrap.connect().sync(); 
  19.             channelFuture.channel().closeFuture().sync(); 
  20.         } catch (Exception e) { 
  21.             e.printStackTrace(); 
  22.         } finally { 
  23.             worker.shutdownGracefully(); 
  24.         } 
  25.     } 

客户端处理Handler

  1.  
  2. public class EchoClientHandler extends ChannelInboundHandlerAdapter { 
  3.     @Override 
  4.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
  5.         ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(); 
  6.         buffer.writeBytes("Hello Netty".getBytes(StandardCharsets.UTF_8)); 
  7.         ctx.channel().writeAndFlush(buffer); 
  8.     } 

4. 客户端源代码介绍

客户端的代码和服务端的代码基本一致,所以这里不做全部讲解,只做不一样的讲解:

  1. EventLoopGroup worker = new NioEventLoopGroup(); 

这里客户端只有一个事件循环组,为什么?因为客户端不存在新连接嘛!

  1. Bootstrap bootstrap = new Bootstrap(); 

这个里和服务端的ServerBootstrap基本一致,是为了保存客户端的配置所设置的一个类!

  1. ChannelFuture channelFuture = bootstrap.connect().sync(); 

连接服务端,并等待链接完成!

Handler的重载方法也发生了变化:

  1. public void channelActive(ChannelHandlerContext ctx) throws Exception {....} 

这里的含义是,当客户端被激活后既链接到服务端后,回调该逻辑!

细心的同学在练习的时候可能会发现一点问题,我们发现客户端会有 handler和childHandler两种方法

  1. .handler() 
  2. //设置服务管道 
  3. .childHandler() 

总结

 

本节课比较简单,主要是对Netty的基本使用有一个比较简单的认知,希望大家课下多练习,争取会简单的使用Netty!

 

来源:源码学徒内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯