-
引导类的层次结构包括一个抽象的父类和两个具体的引导子类,服务器致力于使用一个父 Channel 来接受来自客户端的连接,并创建子 Channel 以用于它们之间的通信;而客户端将最可能只需要一个单独的、没有父 Channel 的 Channel 来用于所有的网络交互;Cloneable便于创建相同配置的引导类的浅拷贝
- 子类型 B 是其父类型的一个类型参数,可以返回运行时的实例的引用以支持方法的链式调用
public abstract class AbstractBootstrap <B extends AbstractBootstrap<B,C>,C extends Channel>
-
ServerBootstrap
可分别设置ServerChannel
和子Channel
的option
和attr
,而Bootstrap
则只创建一个Channel
- 可以从
Channel
引导客户端,简单的例子就是在服务端连接建立后,再作为客户端去连接其他服务(如数据库等)
public class BootstrapSharingEventLoopGroup { public void bootstrap() { 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"); } }); // 复用 EventLoop 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(); } } }); } }
- 抽象类
ChannelInboundHandlerAdapter
定义了initChannel
方法,可将多个ChannelHandler
添加到一个ChannelPipeline
中的简便方法,ChannelInitializer
为其子类,只需重写该方法即可,一旦Channel
被注册到了它的EventLoop
之后,就会调用initChannel
public class BootstrapWithInitializer { public void bootstrap() throws InterruptedException { 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)); } } }
-
ChannelOption
和AttributeKey
将在connect
或者bind
方法被调用时设置到已创建的Channel
上,可在事件处理方法中使用public class BootstrapClientWithOptionsAndAttrs { public void bootstrap() { final AttributeKey<Integer> id = AttributeKey.newInstance("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(); // 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); bootstrap.attr(id, 123456); ChannelFuture future = bootstrap.connect( new InetSocketAddress("www.manning.com", 80)); future.syncUninterruptibly(); } }
-
Bootstrap
也可用于无连接的协议,Netty 提供了各种DatagramChannel
的实现,唯一区别就是不再调用connect
,而只调用bind
public class BootstrapDatagramChannel { public void bootstrap() { 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)); 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应用,关闭EventLoopGroup
,处理任何挂起的事件和任务,随后释放所有活动的线程,返回一个Future,在关闭完成时接收通知public class GracefulShutdown { public static void main(String args[]) { GracefulShutdown client = new GracefulShutdown(); client.bootstrap(); } public void bootstrap() { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler( new SimpleChannelInboundHandler<ByteBuf>() { @Override protected void channelRead0( ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { System.out.println("Received data"); } } ); bootstrap.connect(new InetSocketAddress("www.manning.com", 80)).syncUninterruptibly(); Future<?> future = group.shutdownGracefully(); // block until the group has shutdown future.syncUninterruptibly(); } }
第 8 章 引导
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 6.2 Channel实现 ![Netty_Channel类图][2] Channel的类图比较清晰。我们主要分析...