Netty1:初识Netty
为什么使用Netty
Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性、可扩展性在同类框架中都是首屈一指的,它已经得到了成百上千的商用项目的证明。对于为什么使用Netty这个话题,我们先看一下使用原生的NIO有什么缺点:
- NIO的类库和API繁杂,使用麻烦,需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等,这就像我们会使用Hibernate、MyBatis这些ORM框架而不会直接使用Connection、Statement一样
- 需要其他额外技能作为铺垫,必须对多线程和网络编程非常熟悉才能写出高质量的NIO程序
- 可靠性能力补齐,工作量和难度都非常大,例如客户端面临断线重连、网络闪断、半包读写、失败缓存、网络拥塞、异常码流等问题的处理
- JDK NIO的BUG,例如著名的epoll bug,该问题会导致Selector空轮训,最终导致CPU 100%
也正是因为有种种缺点,因此不建议使用原生的NIO而是建议使用一些比较成熟的NIO框架例如Netty、Mina,这一系列文章讲的是Netty,Netty作为一款高性能NIO框架,其优点总结有:
- API使用简单、开发门槛低
- 功能强大,预置了多种编码解码功能,支持多种主流协议
- 定制能力强,可以通过ChannelHandler对通信框架进行灵活扩展
- 性能高,与业界其他主流NIO框架对比,Netty性能最优
- 成熟、稳定,Netty修复了已经发现的所有JDK NIO的BUG,业务开发人员不需要再为NIO的BUG而烦恼
- 社区活跃、版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会被加入
- 经历了大规模的商业应用考验,质量得到验证
正因为这些优点,Netty逐渐成为了Java NIO变成的首选框架。
Netty入门Demo
下面演示一下Netty的Demo(注:Demo来自Netty权威指南第三章),本文只写代码与演示结果,不做讲解,对Netty的使用基本讲解放在下一篇文章中,循序渐进,先感性地认识Netty,再理性地认识Netty中的东西。
提一下,本文及之后的文章Netty基于5.0.0.Alpha1这个版本,贴一下我自己的Maven配置吧:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.xrq.netty</groupId><artifactId>netty-test</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>5.0.0.Alpha1</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency></dependencies></project>
首先从服务端代码开始,定义一个TimeServer:
1 public class TimeServer { 2 3 public void bind(int port) throws Exception { 4 // NIO线程组 5 EventLoopGroup bossGroup = new NioEventLoopGroup(); 6 EventLoopGroup workerGroup = new NioEventLoopGroup(); 7 8 try { 9 ServerBootstrap b = new ServerBootstrap(); 10 b.group(bossGroup, workerGroup) 11 .channel(NioServerSocketChannel.class) 12 .option(ChannelOption.SO_BACKLOG, 1024) 13 .childHandler(new ChildChannelHandler()); 14 15 // 绑定端口,同步等待成功 16 ChannelFuture f = b.bind(port).sync(); 17 // 等待服务端监听端口关闭 18 f.channel().closeFuture().sync(); 19 } finally { 20 // 优雅退出,释放线程池资源 21 bossGroup.shutdownGracefully(); 22 workerGroup.shutdownGracefully(); 23 } 24 } 25 26 private class ChildChannelHandler extends ChannelInitializer<SocketChannel> { 27 @Override 28 protected void initChannel(SocketChannel arg0) throws Exception { 29 arg0.pipeline().addLast(new TimeServerHandler()); 30 } 31 } 32 33 }
TimeServerHandler这么定义:
1 public class TimeServerHandler extends ChannelHandlerAdapter { 2 3 @Override 4 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 5 ByteBuf buf = (ByteBuf)msg; 6 byte[] req = new byte[buf.readableBytes()]; 7 buf.readBytes(req); 8 9 String body = new String(req, "UTF-8"); 10 System.out.println("The time server receive order:" + body); 11 String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER"; 12 13 ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes()); 14 ctx.write(resp); 15 } 16 17 @Override 18 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 19 ctx.flush(); 20 } 21 22 @Override 23 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 24 ctx.close(); 25 } 26 27 }
即读取来自客户端的数据,如果是"QUERY TIME ORDER",则把当前时间写到Channel中去。至此,Netty服务端代码已经开发完毕。接下来是Netty客户端代码,首先还是TimeClient:
1 public class TimeClient { 2 3 public void connect(int port, String host) throws Exception { 4 EventLoopGroup group = new NioEventLoopGroup(); 5 try { 6 Bootstrap b = new Bootstrap(); 7 8 b.group(group) 9 .channel(NioSocketChannel.class) 10 .option(ChannelOption.TCP_NODELAY, true) 11 .handler(new ChannelInitializer<SocketChannel>() { 12 protected void initChannel(SocketChannel ch) throws Exception { 13 ch.pipeline().addLast(new TimeClientHandler()); 14 }; 15 }); 16 17 // 发起异步连接操作 18 ChannelFuture f = b.connect(host, port).sync(); 19 // 等待客户端连接关闭 20 f.channel().closeFuture().sync(); 21 } finally { 22 // 优雅退出,释放NIO线程组 23 group.shutdownGracefully(); 24 } 25 } 26 27 }
同样的,定义一个TimeClientHandler:
1 public class TimeClientHandler extends ChannelHandlerAdapter { 2 3 private static final Logger LOGGER = LoggerFactory.getLogger(TimeClientHandler.class); 4 5 private final ByteBuf firstMessage; 6 7 public TimeClientHandler() { 8 byte[] req = "QUERY TIME ORDER".getBytes(); 9 firstMessage = Unpooled.buffer(req.length); 10 firstMessage.writeBytes(req); 11 } 12 13 @Override 14 public void channelActive(ChannelHandlerContext ctx) throws Exception { 15 ctx.writeAndFlush(firstMessage); 16 } 17 18 @Override 19 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 20 ByteBuf buf = (ByteBuf)msg; 21 byte[] req = new byte[buf.readableBytes()]; 22 buf.readBytes(req); 23 24 String body = new String(req, "UTF-8"); 25 System.out.println("Now is:" + body); 26 } 27 28 @Override 29 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 30 LOGGER.warn("Unexcepted exception from downstream:" + cause.getMessage()); 31 ctx.close(); 32 } 33 34 }
客户端的操作为打印来自服务端的数据,这样,整个Netty Demo代码就写完了,结构比较清楚,都是一个Server+一个Handler的模式,Handler用于处理读取到的信息。
运行Demo
上面写完了Demo,接着写一下测试代码,很简单,分别运行bind方法和connect方法即可:
1 public class CoreTest { 2 3 @Test 4 public void timeServerTest() throws Exception { 5 new TimeServer().bind(8080); 6 } 7 8 @Test 9 public void timeClientTest() throws Exception { 10 new TimeClient().connect(8080, "127.0.0.1"); 11 } 12 13 }
先运行timeServerTest让服务端先启动,再运行timeClientServer让客户端后启动,运行结果服务端的打印为:
The time server receive order:QUERY TIME ORDER
结合代码可以看到,服务端读取到了来自客户端的数据,数据内容为"QUERY TIME ORDER",接着服务端取自己的时间,传输给客户端,看一下客户端的打印:
Now is:Thu Apr 05 21:07:39 CST 2018
打印了来自服务端的时间,这样,利用Netty进行服务端+客户端的相互通信的Demo完成,有了这个Demo,对Netty有了感性上的认识,接着我们一点一点深入去学习Netty。
Netty1:初识Netty相关推荐
- maven netty 配置_Netty是业界最流行的NIO框架之一:初识Netty
为什么使用Netty Netty是业界最流行的NIO框架之一,它的健壮性.功能.性能.可定制性.可扩展性在同类框架中都是首屈一指的,它已经得到了成百上千的商用项目的证明.对于为什么使用Netty这个话 ...
- Netty专题-(1)初识Netty
写在前面 最近对Netty这一块进行了一下学习,因为之前不是很了解.这里在学习的过程中也跟着做了一些笔记,特意整理在这里,希望对想学习的小伙伴有一定的帮助.这里是从最开始的基础进行学习,所以对于想入门 ...
- Netty入门教程——初识Netty
Netty入门教程之初识Netty,本次会写几篇文章来详细说下netty. 文章目录 什么是Netty 什么是Netty Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一 ...
- Netty学习(一):初识Netty
章节 1.Netty学习(一):初识Netty 2.Netty学习(二):Netty的核心组件 3.Netty学习(三):Netty的流程分析 4.Netty学习(四):Netty零拷贝(转载) 5. ...
- 【初识Netty使用Netty实现简单的客户端与服务端的通信操作Netty框架中一些重要的类以及方法的解析】
一.Netty是什么? Netty 由 Trustin Lee(韩国,Line 公司)2004 年开发 本质:网络应用程序框架 实现:异步.事件驱动 特性:高性能.可维护.快速开发 用途:开发服务器和 ...
- Netty学习笔记(一)--- 初识Netty
什么是Netty 如果在网络上搜索它,你可以在官网上看到如下内容: Netty is an asynchronous event-driven network application framewor ...
- Netty专题-(3)NIO网络编程
之前在上一章Netty专题-(2)NIO三大核心中介绍了NIO的三大核心类Selector . Channel 和 Buffer,这一章我们将利用这些核心进行编程实现相关的一些功能.在正式进入编程之前 ...
- Netty专题-(2)NIO三大核心
在之前的文章Netty专题-(1)初识Netty中提到了NIO三大核心Selector . Channel 和 Buffer,所以在这一章重点会是介绍这三个核心. 1 缓冲区(Buffer) 1.1 ...
- Netty2:粘包/拆包问题与使用LineBasedFrameDecoder的解决方案
什么是粘包.拆包 粘包.拆包是Socket编程中最常遇见的一个问题,本文来研究一下Netty是如何解决粘包.拆包的,首先我们从什么是粘包.拆包开始说起: TCP是个"流"协议,所谓 ...
最新文章
- 技术“摸鱼” 大神,国外小哥 5 年白拿 45 万工资!
- email util demo
- python之simplejson,Python版的简单、 快速、 可扩展 JSON 编码器/解码器
- 八月22日,django知识点总结:
- 【双11狂欢背后】微服务注册中心如何承载大型系统的千万级访问?
- 【MATLAB、深度学习】AlexNet及VGG神经网络在MATLAB上的应用
- 怎么看登陆哪个用户名_面试教材看哪个版本?抽到的版本与备考的不一致怎么办?...
- vue添加滚动事件,解决简书Carol_笑一笑方案中vue移除滚动事件失效的问题
- C++基础——tricks,让人惊艳的那些代码
- PLSQL中文显示乱码
- 腾讯云数据库智能化海量运维的建设与实践
- android 中RecyclerView 嵌套了 GridView 的用法
- 散户通过a股量化数据接口实现自动化实盘交易主要方式有哪些?
- delphi mysql.pas_Delphi 一些pas
- css3循环360度图片旋转
- macbook+外接,导致很卡
- 【时间管理】柳比歇夫之奇特的一生
- 论“蹭热点”,我只服“杜蕾斯”,今天咋们一起来盘点 它曾蹭过的10大神热点!...
- 《headfirst设计模式》读书笔记9-迭代器和组合模式
- 使用python实现固定效应模型
热门文章
- Maven 使用bat批量清除本地仓库的lastUpdated文件
- python进阶(第三章1) 字典
- 初级中级高级_初级职位,(半)高级职位
- sketch钢笔工具_设计工具(Sketch,Adobe XD,Figma和InVision Studio)中奇怪的一项功能
- JavaScript 新增两个原始数据类型
- ORA-01400: 无法将 NULL 插入 (CHARGE_WQRL.SF_JMQTFY_T.BH)
- 从新手机到老股票 闲鱼为何会沦为骗子与营销的新平台?
- 构建LAMP平台及应用系统
- mysql添加普通用户用于管理单一数据库
- nagios的搭建及配置----(中)