一、Netty基础组件介绍

一、Netty基础组件介绍

netty程序demo:

public class NettyServerDemo {


    private final Integer serverPort;
    ServerBootstrap serverBootstrap = new ServerBootstrap();

    public NettyDiscardServer(Integer port){
        serverPort = port;
    }
    public  void runServer(){

        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup();

        try{

            serverBootstrap.group(bossGroup,workGroup)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(serverPort)
                    .option(ChannelOption.SO_KEEPALIVE,true)
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new NettyDiscardHandler());
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind().sync();
            ChannelFuture closeFuture = channelFuture.channel().closeFuture();
            closeFuture.sync();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        new NettyServerDemo (9999).runServer();
    }

}

1、Reactor反应器模式中的IO事件处理流程

流程图:
在这里插入图片描述

第一步:通道注册
第二步:查询选择,不断的轮训,查询选择器中的IO事件
第三步:事件分发,分发到handler
第四步:handler处理,真正的io操作和业务处理。

2、Channel通道组件

常见通道:
NioSocketChannel : 异步非阻塞的TCP Socket传输通道
NioServerSocketChannel:异步非阻塞的TCP Socket服务端监听通道
NioDatagramChannel: 异步非阻塞的UDP传输通道
NioSctpChannel :异步非阻塞的Sctp传输通道
NioSctpServerChannel :异步非阻塞的Sctp服务端监听通道
OioSocketChannel:同步阻塞式TCP Socket传输通道
OioServerSocketChannel:同步阻塞式TCP Socket服务监听通道
OioDatagramChannel:同步阻塞式UDP传输通道
OioSctpChannel:同步阻塞式Sctp传输通道
OioSctpServerChannel:同步阻塞式Sctp服务端监听通道

3、Reactor反应器

一个反应器(SubReactor子反应器)会负责一个事件处理线程,不断轮询,通过Selector选择器不断的查询注册过的IO事件。找到IO事件,分发给handler处理。

Netty的反应器类:NioEventLoop
两个重要属性:
selector 和volatile的thread,这个thread 负责selector选择器IO事件的轮询。
图:
在这里插入图片描述

一个NioEventLoop对应多个Channel管道。

4、Handler处理器

NioEventLoop内的选择器,查询事件,对事件进行分发(dispatch),事件分发的目标就是Netty自己的Handler处理器。

handler分两类:

入站处理器(ChannelInboundHandler):负责读,从上到下。默认实现ChannelInboundHandlerAdapter
出站处理器(ChannelOutboundHandler):负责写,从下到上。默认实现ChannelOutboundHandlerAdapter
图:
在这里插入图片描述

两者都是继承ChannelHandler。

5、Nettty的流水线

ChannelPipeline(通道流水线) 绑定通道和handler的关系,串在一起,形成双线链表。
入站处理器可以截断。
出站处理器不可以,会报异常。

图:
在这里插入图片描述

###6、BootStrap启动类
完成客户端和服务端组件的组装以及Netty程序的初始化。
图:
在这里插入图片描述

父子通道:
EventLoopGroup(事件循环线程组):
socket描述符分为两类:连接监听类型,传输数据类型。

在Netty中,有接收关系的NioServerSocketChannel和NioSocketChannel 叫做父子通道。
NioServerSocketChannel负责连接监听和接收,叫父通道。
对应于每一个接收到的NioSocketChannel传输类通道,叫做子通道。

7、EventLoopGroup线程组

EventLoopGroup线程组 由多个EventLoop组成。是一个多线程版本的反应器。其中的NioEventLoop线程对应一个子反应器(SubReactor)。

构造参数指定EventLoop数量,内部构造多个线程和多个EventLoop子反应器,进行多线程的IO事件和分发。默认是最大可用cpu的2倍。

Netty程序中有两个反应器:一个负责新连接的监听和接受的EventLoopGroup线程组,查询父通道的IO事件。另一个EventLoopGroup线程组负责所有子通道的IO事件,并执行Handler处理器中的业务处理。

8、Bootstrap启动流程

.1、创建反应器线程组,并赋值给ServerBootstrap启动器实例。

 //负责连接监听IO事件
 EventLoopGroup bossGroup = new NioEventLoopGroup(1);
 //负责IO事件和Handler业务处理
 EventLoopGroup workGroup = new NioEventLoopGroup();
 //绑定
 serverBootstrap.group(bossGroup,workGroup)

2、设置通道的IO类型

  serverBootstrap.channel(NioServerSocketChannel.class)

3、设置监听端口

serverBootstrap.localAddress(serverPort)

4、设置传输通道的配置选项

serverBootstrap.option(ChannelOption.SO_KEEPALIVE,true)
               .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)

给父通道设置选项,要是给子通道配置用childOption。
5、装配子通道的ChannelPipeline流水线。

 serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
					@Override
					protected void initChannel(SocketChannel socketChannel) throws Exception {
						socketChannel.pipeline().addLast(new NettyDiscardHandler());
					}
				});

initChannel方法在子通道创建后会被执行,向子通道添加业务处理器。

为什么不给父通道装配流水线?
因为父通道NioServerSocketChannel是连接接受通道,业务比较固定。如果需要,可以使用handler方法装配。

6、绑定服务器新连接的监听端口

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

7、自我阻塞知道通道阻塞

ChannelFuture closeFuture = channelFuture.channel().closeFuture();

8、关闭EventLoopGroup

orkGroup.shutdownGracefully();
bossGroup.shutdownGracefully();

9、测试入站处理器的方法执行时机:

InHandlerDemo类继承ChannelInboundHandlerAdapter

public class InHandlerDemo extends ChannelInboundHandlerAdapter {
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerAdded() 被调用");
        super.handlerAdded(ctx);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelRegistered() 被调用");
        super.channelRegistered(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelActive() 被调用");
        super.channelActive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead() 被调用");
        super.channelRead(ctx, msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelReadComplete() 被调用");
        super.channelReadComplete(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelInactive() 被调用");
        super.channelInactive(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelUnregistered() 被调用");
        super.channelUnregistered(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerRemoved() 被调用");
        super.handlerRemoved(ctx);
    }
}

测试类

public class InHandlerDemoTest {
    public static void main(String[] args) throws InterruptedException {


        InHandlerDemo inHandlerDemo = new InHandlerDemo();
        ChannelInitializer<EmbeddedChannel> channelInitializer = new ChannelInitializer<EmbeddedChannel>() {
            @Override
            protected void initChannel(EmbeddedChannel ch) throws Exception {
                ch.pipeline().addLast(inHandlerDemo);
            }
        };

        EmbeddedChannel embeddedChannel = new EmbeddedChannel(channelInitializer);
        ByteBuf buffer = Unpooled.buffer();
        buffer.writeInt(1);

        embeddedChannel.writeInbound(buffer);
        embeddedChannel.flush();

        embeddedChannel.writeInbound(buffer);
        embeddedChannel.flush();
        embeddedChannel.close();

        TimeUnit.SECONDS.sleep(10000);
    }
}

输出结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值