netty系列(四)--netty模型及入门案例

什么是netty?

Netty 是由 JBOSS 提供的一个 Java 开源框架,现为 Github上的独立项目。
Netty 是一个异步的、基于事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络 IO 程序。

Netty主要针对在TCP协议下,面向Clients端的高并发应用,或者Peer-to-Peer场景下>的大量数据持续传输的应用。
Netty本质是一个NIO框架,适用于服务器通讯相关的多种应用场景
要透彻理解Netty , 需要先学习 NIO , 这样我们才能阅读 Netty 的源码

Reactor模式

基本原理:

传统的BIO模型会造成大量线程的浪费
针对传统BIO的缺点,reactor解决方案:

  • 基于I/O复用模型,多个连接公用一个阻塞对象,应用程序只需要在一个阻塞对象等待,当某个连接有新的数据可以处理时,操作系统通知应用程序,程序从阻塞状态返回,开始处理业务
  • 基于线程池服用,不必为每个连接创建线程,一个线程可以处理多个业务

reactor核心组成:

  • Reactor:负责监听和分发事件
    Handlers :负责处理程序执行I/O事件要完成的实际事件

架构图:
在这里插入图片描述

Netty模型简单图解

在这里插入图片描述

  • BossGroup线程维护Selector,只关注Accecpt
  • 当接受到Accept事件,获取对应的SocketChannel,封装成NIOSocketChannel并注册到Woker线程,并由Woker线程维护
  • Woker线程监听到Selector中的通道发生了自己感兴趣的事件后,就进行处理
  • Woker线程出了Handler进行处理事件

进阶版图解

在这里插入图片描述

  • Netty抽象出两组线程池,BossGroup专门负责接收客户端的连接,WorkGroup负责网络的读写
  • BossGourp和WorkGroup类型都是NIOEventLoopGroup
  • NioEventLoopGroup相当于一个事件循环组,这个族中含有多个事件循环,每一个事件循环都是NioEventLoop
  • NioEventLoop表示一个不断循环的执行处理任务的线程,每个NioEventLoop都有一个Selector,用于监听绑定在其上的socket的网络通讯

每个Boss NIOEventLoop执行步有三步

  • 轮询 accept事件
  • 处理accept事件,与client建立连接,生成NioSocketChannel,并将其注册到某个woker NIOEventLoop上的selector,
  • 处理任务队列的任务,即runAllTasks

每个Woker NIOEventLoop循环执行的步骤:

  • 轮询 read,write事件,
  • 处理I/O事件,即read,write事件,在对应的NioSocketChannel处理
  • 处理任务队列的任务,即runAllTasks

Netty入门Demo:

需求在这里插入图片描述
服务端代码:


public class server {
    public static void main(String[] args) throws InterruptedException {
        //创建BossGroup和WorkerGroup
        EventLoopGroup bossGroup=new NioEventLoopGroup();
        EventLoopGroup workerGroup=new NioEventLoopGroup();
        //创建服务器端的启动对象,配置参数
        ServerBootstrap bootstrap=new ServerBootstrap();
        //使用链式编程进行设置
        bootstrap.group(bossGroup,workerGroup)//设置两个线程组
                .channel(NioServerSocketChannel.class)//使用NioServerSocketChannel,作为服务器的通道实现
                .option(ChannelOption.SO_BACKLOG,128)//设置线程队列的连接个数
                .childOption(ChannelOption.SO_KEEPALIVE,true)//设置保持活动连接状态
                .childHandler(new ChannelInitializer<SocketChannel>() {//创建一个通道测试对象
                    //给pipeline设置处理器
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                         socketChannel.pipeline().addLast(new serverHandler());//自定义的处理器
                    }
                });
        System.out.println("....server is ready");
        ChannelFuture future = bootstrap.bind(6668).sync();
        //对关闭通道进行监听,只有关闭事件的时候次才会关闭
        future.channel().closeFuture().sync();
    }
}

服务端handler:

//自定义Handler
public class serverHandler extends SimpleChannelInboundHandler {
    @Override
    //channelHandlerContext ctx:含有管道pipeline,通道,地址等
    //object o--客户端发送的数据
    protected void messageReceived(ChannelHandlerContext ctx, Object o) throws Exception {
        System.out.println("server ctx="+ctx);
        //将msg转成一个ByteBufer
        ByteBuf buf=(ByteBuf)o;
        System.out.println("客户端发送的消息是:"+buf.toString(CharsetUtil.UTF_8));
        System.out.println("客户端地址:"+ctx.channel().remoteAddress());
    }

    @Override
    //数据读取完毕
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //将数据写入到缓存,并刷新
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端~!",CharsetUtil.UTF_8));

    }

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

客户端代码:

public class client {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup eventExecutors=new NioEventLoopGroup();
        Bootstrap bootstrap=new Bootstrap();
        bootstrap.group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new ClientHandler());//加入自己的处理其
                    }
                });
        System.out.println("-----客户端Ok!!!");
        //
        ChannelFuture future=bootstrap.connect("127.0.0.1",6668).sync();
        future.channel().closeFuture().sync();
    }
}

客户端handler:`

public class ClientHandler extends SimpleChannelInboundHandler {
    @Override
    protected void messageReceived(ChannelHandlerContext ctx, Object o) throws Exception {

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client "+ctx);
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello,server:im client", CharsetUtil.UTF_8));
    }
     //当通道有事件时,会触发
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf=(ByteBuf)msg;
        System.out.println("服务器回复的消息:"+buf.toString(CharsetUtil.UTF_8));
        System.out.println("服务器的地址:"+ctx.channel().remoteAddress());
    }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值