博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
搞懂Netty(1)一个简单的表白小案例(使用Springboot整合开发)
阅读量:4036 次
发布时间:2019-05-24

本文共 6304 字,大约阅读时间需要 21 分钟。

写了很久的java并发包里面的文章,今天换一个口味。很早之前学的Netty,由于最近项目经常使用到,遇到了很多坑,因此想通过一个体系教程说一下这个高性能异步通信框架Netty,这也是netty的第一篇文章。主要是通过Springboot来整合Netty实现一个最基本的案例。

一、Netty是什么

想认识Netty最好的方式就是直接去官网看文档,由于文档是英文,因此直接在这里翻译过来了。

Netty是一个高性能、异步事件驱动的NIO框架,支持如TCP、UDP协议和传输文件。“高性能”并不意味着程序会出现各种性能或其他问题。它是一种精心设计的框架,其灵活性、稳定性依然能够得到保证。

官网说这个Netty特别好,毕竟是自家的产品,不过好不好还是用户说了才可以,通过实践证明,目前Netty是我们业界最流行的NIO框架,无数个商业项目也已经验证了。毕竟java的NIO框架开发起来太恶心,而且还有各种bug没有解决。

为什么我们要首选Netty呢?之前看的书列举了很多条,不过最根本的我觉得还是这几个:使用简单、功能强大、性能高、开发无烦恼。无烦恼是因为bug较少,而且也比较成熟。

相信你看这篇文章,可能是项目中要用到,也可能只是想学习一个新技能。不管是出于什么目的,通过上面的分析,你就会发现这个Netty真的是很有必要了解学习。下面我们就直接上手写个最基本的案例吧。

二、案例实现

这个是一个客户端服务端简单通信的案例,假设服务端是个女孩,客户端男孩向其表白。

男孩:I love you

女孩:no

男孩:不灰心不丧气,继续爱你

1、前提准备

如果你是Springboot直接在maven中添加依赖即可

io.netty
netty-all
5.0.0.Alpha1

如果你没有使用maven那么直接去官网或者是百度下载一个netty-all-5.0.0.Alpha1的jar包导入即可。

2、服务端(女孩)开发

我们直接看代码,再来分析其流程。

@Componentpublic class NettyServer {
EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup work = new NioEventLoopGroup(); @PostConstruct public void start() throws InterruptedException {
ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(boss, work) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .childOption(ChannelOption.SO_KEEPALIVE, true) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer
() {
public void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new ServerUAVHandler()); } }); ChannelFuture cf = bootstrap.bind(8888).sync(); if (cf.isSuccess()){
System.out.println("启动成功"); } } @PreDestroy private void destory() throws Exception{
boss.shutdownGracefully(); work.shutdownGracefully(); System.out.println("关闭server"); }}

基本流程最好对照着代码来看,这样理解的会更加深刻。

(1)new了两个NioEventLoopGroup,一个是boss,一个是work。NioEventLoopGroup是一个线程组,boss线程组用于接收客户端的连接工作,work线程组用于处理数据。

(2)在start方法中,首先new了一个ServerBootstrap,,名字叫bootstrap。它是netty用于启动NIO服务端的辅助启动类。目的是降低服务端的开发复杂度。

(3).group(boss, work)目的是将两个线程组传入,让其工作。

(4).channel(NioServerSocketChannel.class)就类比与NIO中的ServerSocketChannel。

(5).option(ChannelOption.SO_BACKLOG, 1024)配置TCP参数,将其中一个参数backlog设置为1024,表明临时存放已完成三次握手的请求的队列的最大长度。

(6).childOption(ChannelOption.SO_KEEPALIVE, true)设置TCP长连接,一般如果两个小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文。

(7).handler(new LoggingHandler(LogLevel.INFO))处理Log日志。

(8).childHandler,用于处理客户端的IO事件,比如有一个客户端发起请求,要读取数据,就可以使用这里面的类来处理这个事件。这是整个处理的核心。也是我们自己主要关注的类。

(9)ChannelFuture cf = bootstrap.bind(8888).sync();绑定监听端口。使用sync方法阻塞一直到绑定成功。

(10)下面通过一个if语句表明,如果绑定成功那就输出“服务端启动成功”。

(11)最后将boss和work使用finally代码块优雅的退出。何为优雅今后再说。

其实上面的这些代码都是固定模式的,也就是说你使用的时候直接就可以用了,最核心的就是如何处理客户端的各种事件,比如说有客户端连接、读、写数据等等相关事件。看看ServerUAVHandler类是如何实现的,

public class ServerUAVHandler extends ChannelHandlerAdapter {
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req,"UTF-8"); System.out.println("客户端信息是:"+body); ByteBuf resp = Unpooled.copiedBuffer("no".getBytes()); ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); }}

基本流程如下:

(1)ServerUAVHandler继承了ChannelHandlerAdapter主要是用于处理网络的读写事件。

(2)重写了channelRead读方法,在这个方法内部可以读取客户端的请求信息。其中一个参数msg就是封装的信息对象。我们可以在内部通过ByteBuf这个工具类进行读取。内部实现的细节就不再多描述了。

3、客户端(男孩)开发

@Componentpublic class NettyClient {
private SocketChannel socketChannel; EventLoopGroup group = new NioEventLoopGroup(); @PostConstruct public void start() throws Exception {
//boss 线程组用于处理连接工作 try{
Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE,true) .handler(new ChannelInitializer
() {
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientHandler()); } }); //绑定端口 ChannelFuture cf = b.connect("127.0.0.1",8888).sync(); if(cf.isSuccess()){
System.out.println("链接服务器成功"); } cf.channel().closeFuture().sync(); }finally{
group.shutdownGracefully(); } }}

从上面的代码我们会发现,和服务器端的类似,我们在这里主要关注于和服务器有什么不一样,可能是年龄越来越大,你在对比的时候一定要返回去看看,不仅可以加深印象,还可能突然就恍然大悟了。

(1)首先,只new了一个NioEventLoopGroup,因为不需要处理连接,所以客户端只关注于读写数据的操作。

(2)在start方法内部创建了一个Bootstrap,名字是b,意思是客户端的启动类。

(3)接着使用option配置一些参数。

(4)使用handler方法传递一个类,在内部有一个ClientHandler类,同样也是客户端的核心。

(5)接下来链接服务器,指定地址和端口。最终关闭链接优雅的推出线程组。

上面的代码都是模板代码,你可以直接拿来用,在后期越来越深入的时候再来修改。在这里我们还是主要关注一下这个ClientHandler类吧。

public class ClientHandler extends ChannelHandlerAdapter {
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception {
byte[] req = "I love you".getBytes(); ByteBuf first = Unpooled.buffer(req.length); first.writeBytes(req); ctx.writeAndFlush(first).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req,"UTF-8"); if("no".equals(body)){
ByteBuf resp = Unpooled.copiedBuffer("不灰心不丧气,继续我爱你".getBytes()); ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } }}

在这里客户端,首先给服务端发送一个消息“I Love you ”。然后如果收到的是no回复,再说一次“不灰心不丧气,继续我爱你”。这里重写了两个方法channelActive和channelRead方法,第一个是连接到服务端的时候调用,一个是读取服务端的信息调用。

三、总结

通过以上的分析,不知道你能否体会到Netty带来的方便,其实NettyServer类和NettyClient都是模板类,我们只需要关注于这个handler处理类即可,而且相关的处理方法,我们可以直接通过重写就可以实现。再回想一下NIO编程客户端和服务端通信的时候,代码写的都想XX。

OK,今天的文章就先说到这里吧,对了学习最好的方式就是动手敲一遍,有时候看着很简单,但是真实的操作一遍就会遇见很多坑。

在这里插入图片描述

转载地址:http://vibdi.baihongyu.com/

你可能感兴趣的文章
[互联网关注]李开复教大学生回答如何学好编程
查看>>
[关注大学生]李开复给中国计算机系大学生的7点建议
查看>>
[关注大学生]大学毕业生择业:是当"鸡头"还是"凤尾"?
查看>>
[茶余饭后]10大毕业生必听得歌曲
查看>>
gdb调试命令的三种调试方式和简单命令介绍
查看>>
C++程序员的几种境界
查看>>
VC++ MFC SQL ADO数据库访问技术使用的基本步骤及方法
查看>>
VUE-Vue.js之$refs,父组件访问、修改子组件中 的数据
查看>>
Vue-子组件改变父级组件的信息
查看>>
Python自动化之pytest常用插件
查看>>
Python自动化之pytest框架使用详解
查看>>
【正则表达式】以个人的理解帮助大家认识正则表达式
查看>>
性能调优之iostat命令详解
查看>>
性能调优之iftop命令详解
查看>>
非关系型数据库(nosql)介绍
查看>>
移动端自动化测试-Windows-Android-Appium环境搭建
查看>>
Xpath使用方法
查看>>
移动端自动化测试-Mac-IOS-Appium环境搭建
查看>>
Selenium之前世今生
查看>>
Selenium-WebDriverApi接口详解
查看>>