netty(七)--Bootstrap

引导一个应用程序是指对它进行配置,并使他运行起来的过程。
在这里插入图片描述
服务器致力于使用一个父 Channel 来接受
来自客户端的连接, 并创建子 Channel 以用于它们之间的通信;而客户端将最可能只需要一个
单独的、 没有父 Channel 的 Channel 来用于所有的网络交互。


bootstrap类的API

名称 描述
Bootstrap group(EventLoopGroup g) 设置用于处理channel所有事件的eventLoop
Bootstrap channel(class),Bootstrap channelFactory 指定channel的实现类,或者工厂类作为参数
Bootstrap localAddress(socketaddress) 指定channel应该绑定的本地地址。指定channel应该绑定到的地址,如果没有指定,将由操作系统创建一个随机的地址。或者,也可以通过bind()或者connect方法指定localAddress
Bootstrap option(channelOption,T) 设置channelOption,其将被应用到每个新创建的channel的channelConfig。这些选项将会通过bind或者connect方法设置到channel。这个方法对于已经被创建的线程无效
Bootstrap attr(key,val) 指定新创建的channel属性值,作用同上
Bootstrap handler(ChannelHandler) 设置将被添加到ChannelPipeline以接收事件通知的channelHandler
Bootstrap clone() 创建一个Boostrap的克隆,具有和原始bootstrap相同的设置信息
Boostrap remoteAddress 设置远程地址,或者通过connect方法指定
channelFuture connect() 连接到远程节点并返回一个channelFuture,其将会在连接操作完成后接到通知
channelFuture bind() 绑定channel并返回一个channelFuture,其将会在绑定操作完成后接收到通知,在那之后必须调用channel,connect方法来建立连接。

引导客户端

bootstrap类负责为客户端和使用无连接协议的应用程序创建channel。
在这里插入图片描述

channel和EventLoopGroup的兼容性

在这里插入图片描述
不能混用具有不同前缀的组件。
在引导的过程中,在调用 bind()或者 connect()方法之前,必须调用以下方法来设置所需的组件:

  • group();
  • channel()或者 channelFactory();
  • handler()。

如果不这样做, 则将会导致 IllegalStateException。对 handler()方法的调用尤其重要,因为它需要配置好 ChannelPipeline。

引导服务器

ServerBootstrap类的方法

名称 描述
group 设置serverBootstrap要用的EventLoopGroup。这个EventLoopGroup将用于ServerChannel和被接受的子Channel的I/O处理
channel 设置将要被实例化的ServerChannel类
channelFactory 如果不能通过默认的构造函数创建Channel,可以提供一个ChannelFactory
localAddress 指定serverchannel应该绑定到的本地地址,如果没有指定,则将由操作系统使用一个随即地址,或者通过bind方法来指定改localAddress
option 指定要应用到新创建的 ServerChannel 的 ChannelConfig 的 ChannelOption。 这些选项将会通过 bind()方法设置到 Channel。在 bind()方法被调用之后, 设置或者改变 ChannelOption 都不会有任何的效果。所支持的 ChannelOption 取决于所使用的 Channel 类型。
childOption 指定当子channel被接受时,应用到子Channel的ChannelConfig的channelOption。
attr 指定serverChannel的属性,属性将通过bind方法设置给channel
childAttr 将属性设置给已经被接受的子channel
handler 设置被添加到serverChannel的channelPipeline中的channelHandler
childHandler 设置将被添加到的已被接受的子channel的channelpipeline中的channelhandler。
bind 绑定serverChannel并且返回一个ChannelFuture,其将在绑定操作完成后收到通知

ServerChannel 的实现负责创建子 Channel,这些子 Channel 代表了已被接受的连接。
在这里插入图片描述


假设你的服务器正在处理一个客户端的请求, 这个请求需要它充当第三方系统的客户端。当一个应用程序(如一个代理服务器)必须要和组织现有的系统(如 Web 服务或者数据库)集成时,就可能发生这种情况。 在这种情况下,将需要从已经被接受的子 Channel 中引导一个客户端 Channel。
在这里插入图片描述

ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.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(
new SimpleChannelInboundHandler<ByteBuf>() {
@Override
protected void channelRead0(
ChannelHandlerContext ctx, ByteBuf in)
throws Exception {
System.out.println("Received data");
}
} );
bootstrap.group(ctx.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();
}
}
} );

在引导过程中添加多个 ChannelHandler,使用自定义的ChannelInitializer。

protected void initChannel(Channel ch) throws Exception {
	ChannelPipeline pipeline = ch.pipeline();
	pipeline.addLast(new HttpClientCodec());
}

DatagramChannel

前面的引导都是基于TCP协议的SocketChannel,对于无连接的协议,netty提供了各种DatagramChannel的实现。

 public void serve(){
        Bootstrap bootstrap=new Bootstrap();
        bootstrap.group(new OioEventLoopGroup())
                .channel(OioDatagramChannel.class)
                .handler(new SimpleChannelInboundHandler<DatagramPacket>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {

                    }
                });
        ChannelFuture future=bootstrap.bind(new InetSocketAddress(0));//该协议是无连接的
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()){
                    System.out.println("channel bind");
                }else {
                    System.out.println("channel bind failed");
                    channelFuture.cause().printStackTrace();
                }
            }
        });
    }

调用 EventLoopGroup.shutdownGracefully()方法关闭 EventLoopGroup, 它将处理任何挂起的事件和任务,并且随后
释放所有活动的线程。

猜你喜欢

转载自blog.csdn.net/ljz2016/article/details/82855318