美文网首页
Netty学习--引导

Netty学习--引导

作者: 何何与呵呵呵 | 来源:发表于2019-01-23 08:22 被阅读0次
Bootstrap 类
引导类的层次结构

注:为什么引导类是Cloneable 的?
只会创建引导类实例的EventLoopGroup的一个浅拷贝,所以,将在所有克隆的Channel实例之间共享。这是可以接受的,因为通常这些克隆的Channel的生命周期都很短暂,一个典型的场景是——创建一个Channel以进行一次HTTP请求。

引导客户端和无连接协议
API
  • 引导客户端
引导过程
EventLoopGroup group = new NioEventLoopGroup(); // 设置EventLoopGroup,提供用于处理Channel事件的EventLoop
Bootstrap bootstrap = new Bootstrap(); // 创建一个Bootstrap类的实例以创建和连接新的客户端
Channel
bootstrap.group(group)
    .channel(NioSocketChannel.class) // 指定要使用的Channel 实现
    .handler(new SimpleChannelInboundHandler<ByteBuf>() { // 设置用于Channel 事件和数据的ChannelInboundHandler
        @Override
        protected void channeRead0(ChannelHandlerContext channelHandlerContext,ByteBuf byteBuf) throws Exception {
            System.out.println("Received data");
        }
    } );
ChannelFuture future = bootstrap.connect(new InetSocketAddress("www.manning.com", 80)); // 连接到远程主机
    future.addListener(new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture channelFuture) throws Exception {
            if (channelFuture.isSuccess()) {
                System.out.println("Connection established");
            } else {
                System.err.println("Connection attempt failed");
                channelFuture.cause().printStackTrace();
            }
        }
    } );
  • Channel 和EventLoopGroup 的兼容性
channel // 相互兼容的EventLoopGroup 和Channel
├───nio
│         NioEventLoopGroup
├───oio
│         OioEventLoopGroup
└───socket
    ├───nio
        │ NioDatagramChannel
        │ NioServerSocketChannel
        │ NioSocketChannel
    └───oio
        │ OioDatagramChannel
        │ OioServerSocketChannel
        │ OioSocketChannel
引导服务器
  • ServerBootstrap 类
ServerBootstrap 类的方法
  • 引导服务器
ServerBootstrap 和ServerChannel
NioEventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(group)
    .channel(NioServerSocketChannel.class)
    .childHandler(new SimpleChannelInboundHandler<ByteBuf>() {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx,ByteBuf byteBuf) throws Exception {
            System.out.println("Received data");
            }
        } );
ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080));
future.addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture channelFuture)throws Exception {
    if (channelFuture.isSuccess()) {
        System.out.println("Server bound");
    } else {
        System.err.println("Bound attempt failed");
        channelFuture.cause().printStackTrace();
    }
}
} );
从Channel 引导客户端
在两个Channel 之间共享EventLoop

通过将已被接受的子Channel 的EventLoop 传递给Bootstrap的group()方法来共享该EventLoop。因为分配给EventLoop 的所有Channel 都使用同一个线程,所以这避免了额外的线程创建,以及前面所提到的相关的上下文切换。

ServerBootstrap bootstrap = new ServerBootstrap(); // 创建ServerBootstrap 以创建ServerSocketChannel,并绑定它
        bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup()) // 设置EventLoopGroup,其将提供用 以处理Channel 事件的EventLoop
                .channel(NioServerSocketChannel.class)
                .childHandler(
                        new SimpleChannelInboundHandler<ByteBuf>() {
                            ChannelFuture connectFuture;
                            @Override
                            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                Bootstrap bootstrap = new Bootstrap();
                                bootstrap.channel(NioSocketChannel.class).handler( // 指定Channel的实现
                                        new SimpleChannelInboundHandler<ByteBuf>() {
                                            @Override
                                            protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
                                                System.out.println("Received data");
                                            }
                                        } );
                                bootstrap.group(ctx.channel().eventLoop()); // 使用与分配给已被接受的子Channel相同的EventLoop
                                connectFuture = bootstrap.connect(new InetSocketAddress("www.manning.com", 80));
                            }
                            @Override
                            protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
                                if (connectFuture.isDone()) {
                                    // do something with the data
                                }
                            }
                        } );
        ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080));
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()) {
                    System.out.println("Server bound");
                } else {
                    System.err.println("Bind attempt failed");
                    channelFuture.cause().printStackTrace();
                }
            }
        } );

编写Netty 应用程序的一个一般准则:尽可能地重用EventLoop,以减少线程创建所带来的开销。

在引导过程中添加多个ChannelHandler

利用ChannelInitializer的initChannel方法添加,添加完之后自动移除ChannelInitializer.

ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup())
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializerImpl());
ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080));
future.sync();
final class ChannelInitializerImpl extends ChannelInitializer<Channel> {②
    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpClientCodec());
        pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
    }
}
使用Netty 的ChannelOption 和属性
final AttributeKey<Integer> id = new AttributeKey<Integer>("ID"); // 定义属性
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new NioEventLoopGroup())
    .channel(NioSocketChannel.class)
    .handler(new SimpleChannelInboundHandler<ByteBuf>() {
        @Override
        public void channelRegistered(ChannelHandlerContext ctx)throws Exception {
            Integer idValue = ctx.channel().attr(id).get(); // 设置属性id
            // do something with the idValue
        }
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext,ByteBuf byteBuf) throws Exception {
            System.out.println("Received data");
        }
    }
);
bootstrap.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000); // 利用ChannelOption 设置channel的属性
bootstrap.attr(id, 123456); // 设置用户ID为123456
ChannelFuture future = bootstrap.connect(new InetSocketAddress("www.manning.com", 80));
future. syncUninterruptibly();
引导DatagramChannel

前面的引导代码示例使用的都是基于TCP 协议的SocketChannel,但是Bootstrap 类也可以被用于无连接的协议。为此,Netty 提供了各种DatagramChannel 的实现。唯一区别就是,不再调用connect()方法,而是只调用bind()方法.

Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new OioEventLoopGroup()).channel(OioDatagramChannel.class).handler(
    new SimpleChannelInboundHandler<DatagramPacket>(){
        @Override
        public void channelRead0(ChannelHandlerContext ctx,DatagramPacket msg) throws Exception {
            // Do something with the packet
        }
    }
);
ChannelFuture future = bootstrap.bind(new InetSocketAddress(0)); // 调用bind()方法,因为该协议是无连接的
future.addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture channelFuture)throws Exception {
        if (channelFuture.isSuccess()) {
            System.out.println("Channel bound");
        } else {
            System.err.println("Bind attempt failed");
            channelFuture.cause().printStackTrace();
        }
    }
});
关闭

需要优雅地将它关闭,调用EventLoopGroup.shutdownGracefully()方法.

相关文章

  • Netty学习--引导

    Bootstrap 类 引导类的层次结构注:为什么引导类是Cloneable 的?只会创建引导类实例的EventL...

  • Netty学习 - Bootstrap引导

    引导 在Netty中,有两种引导,一是Bootstrap,用于引导客户端或者无连接服务器;另一种便是ServerB...

  • Netty源码愫读(六)ServerBootstrap相关源码学

    BootStrap在netty的应用程序中负责引导服务器和客户端。netty包含了两种不同类型的引导: 使用服务器...

  • Netty学习之Netty介绍

    Netty学习之Netty介绍 前言 本周开始学习Netty,主要的参考资料是《Netty In Action》原...

  • Netty

    【Bootstrap、ServerBootstrap】: Bootstrap 意思是引导,一个 Netty 应用通...

  • Netty核心组件

    Bootstrap、ServerBootstrap Bootstrap 意思是引导,一个 Netty 应用通常由一...

  • java-netty

    netty常用API学习 netty简介 Netty是基于Java NIO的网络应用框架. Netty是一个NIO...

  • Netty | 第2章 Netty 简介《Netty In Ac

    前言 参考资料: 《Netty In Action》; 本系列为 Netty 学习笔记,本篇介绍总结Netty 简...

  • Netty 编码解码

    参考来源 Netty实践 Netty 4.x学习笔记 - Channel和Pipeline Netty 编码器和解...

  • netty

    最近有个项目要用到netty,对于netty进行了研究,简单的总结一下。 学习netty的意义 学习网络编程,怎样...

网友评论

      本文标题:Netty学习--引导

      本文链接:https://www.haomeiwen.com/subject/gcuqjqtx.html