欢迎来到我的博客小站。  交流请加我微信好友: studyjava。  也欢迎关注同名公众号:Java学习之道

Netty框架学习之(二):Netty入门Demo详解

  |   0 评论   |   0 浏览

今天通过一个入门案例来共同学习以下netty框架的简单应用.

工具

idea(eclipse),jdk1.8及以上

假设你以上所需的工具都已经准备好了,那我们就开始我们的学习之旅吧

这篇文章的主旨是了解netty框架的一个demo案列的讲解,如果想了解netty是什么或者说netty的一些特性或功能的,可以自行百度.

废话不多说了,直接进入我们今天的主题吧.
1,jar包下载

想要使用netty框架的话首先的需要下载netty的jar包,这里推荐一个还算挺好用的jar包下载仓库.sonatype.

image.png
这是首页,出现的头像是对此仓库做出贡献的人的感谢.
直接在搜索框中输入netty-all即可,之后确认以下Group-ID和version,我们这里用的是IO-netty家的,版本是最新的5.0.0.Alpha.
image.png
点击对应的版本直接进去下载即可,有好几种下载方式,这里我们选择jar包下载.
image.png
下载完成后在你的下载目录会看见这样一个jar文件,至此jar包下载完成.jar文件名即你下载的名称及版本.
image.png

2,创建工程

打开idea,创建工程,因为demo并不复杂,故创建一个普通工程即可.
下图是创建完成后的工程目录,lib用来存放管理工程所需要的jar包,src下是项目的主体.
image.png
接下来就是把jar包加载进工程了.
file-->Project Structure

image.png
点击Library,点击+好,之后找到你自己的工程里lib文件夹下的jar包,点击ok.
image.png
Classes中既是你添加的jar包,点击apply即可.
image.png
3,接下来就是代码了,下面我们一个类一个类来推进.
3.1 TimeServer的编写

package com.el;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class TimeServer {
public void bind(int port) throws Exception {
//创建两个NioEventLoopGroup线程组,一个用于服务端接收连接,一个用于进行SocketChannel的网络读写
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//创建Nio服务端的辅助启动类
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChildChannelHandler());
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
//优雅推出机制,放在finally代码块内
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}

}
private class ChildChannelHandler extends ChannelInitializer {
@Override
protected void initChannel(SocketChannel sch) throws Exception {
sch.pipeline().addLast(new TimeServerHandler());
}
}
public static void main(String[] args) throws Exception {
//设置固定端口,之后校验端口是否可以更改.
int port = 8080;
if(args !=null&& args.length>0){
try {
port =Integer.valueOf(args[1]);
} catch (NumberFormatException e){
e.printStackTrace();
}
}
//调用自己写的bind方法来启动
new TimeServer().bind(port);
}
}
  • 利用辅助类的group方法将两个线程组当作参数传递到ServerBootStrap中
  • 接着设置channal为NioServerSocketChannel
  • 之后设置channal为NioServerSocketChannel的TCP参数,这里将数组设置为1024
  • 最后绑定IO事件的处理类ChildChannelHandler,用于处理网络IO事件.
  • 服务端启动完成后调用bind方法绑定端口并设置监听.

下面来看一下TimeServerHandler的代码

package com.el;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

import java.util.Date;

public class TimeServerHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//将msg转换成Netty的ByteBuf对象
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body =new String(req,"UTF-8");
System.out.println("The time server receive order :"+body);
String currentTime = "Time".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
//创建一个新的ByteBuf对象来存时间
ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
//异步发送消息给客户端
ctx.write(resp);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
  • flush():发送队fas列中的消息写入到SocketChannel中发送给对方
  • close():当发生异常时,关闭ChannelHandlerContext,释放资源.

3,TimeClient代码:

package com.el;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class TimeClient {
    public void connect(int port,String host) throws Exception {
        //配置客户端NIO线程组
        NioEventLoopGroup Group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(Group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel sch) throws Exception {
                            sch.pipeline().addLast(new TimeClientHandler());
                        }
                    });
            //发起异步连接操作
            ChannelFuture f = b.connect(host,port).sync();
            //等待客户端链路关闭
            f.channel().closeFuture().sync();
        } finally {
            //优雅退出,释放NIO线程组
            Group.shutdownGracefully();
        }

    }
    public static void main(String[] args) throws Exception {
        int port = 8080;
        if(args !=null&& args.length>0){
            try {
                port =Integer.valueOf(args[1]);
            } catch (NumberFormatException e){
                e.printStackTrace();
            }
        }
	    //调用connet方法发起异步连接
            new TimeClient().connect(port,"127.0.0.1");
    }
}

4,TimeClientHandler代码:

package com.el;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAppender;
import io.netty.channel.ChannelHandlerContext;

public class TimeClientHandler extends ChannelHandlerAppender {

    private final ByteBuf firstMessage;

    public TimeClientHandler() {
        byte[] req = "QUERY TIME ORDER".getBytes();
        firstMessage = Unpooled.buffer(req.length);
        firstMessage.writeBytes(req);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(firstMessage);
    }

    @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("Now is :"+body);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //释放资源
        ctx.close();
    }
}

5,结果演示
先启动server端,再启动client端,展示结果如下:
server结果:
image.png
client结果:
image.png

总结:client发起请求的字符```"QUERY TIME ORDER",server端经过校验后返回当前时间给client端.

至此,关于netty框架的一个简单demo就说完了,大家有疑惑或者见解都可以提出来,我也是新人,大家互相学习互相进步吧,谢谢!!!

标题:Netty框架学习之(二):Netty入门Demo详解
作者:tangdou
地址:https://www.mmzsblog.cn/articles/2020/08/09/1596972099745.html
-----------------------------
如未加特殊说明,此网站文章均为原创。
网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
公众号转载请联系网站首页的微信号申请白名单!

个人微信公众号 ↓↓↓                 

微信搜一搜 Java 学习之道