Netty源码分析:ServerBootstrap
2017-09-23 23:39
896 查看
Netty源码分析:ServerBootstrap
一般服务端的代码如下所示:package com.wrh.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * Created by wuranghao on 2017/9/4. */ public final class SimpleServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new SimpleServerHandler()) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { } }); ChannelFuture f = b.bind(8888).sync(); f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } private static class SimpleServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("channelActive"); } @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("channelRegistered"); } @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { System.out.println("handlerAdded"); } } }
在上篇博文(http://blog.csdn.net/u010412719/article/details/78006968)中 剖析了如下的两行代码内部的构造函数中干了些什么。
EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup();
具体可以见上篇博文,对于如上的两行代码得到的结论是:
1、 如果不指定线程数,则线程数为:CPU的核数*2
2、根据线程个数是否为2的幂次方,采用不同策略初始化chooser
3、产生nThreads个NioEventLoop对象保存在children数组中。
可以理解NioEventLoop就是一个线程,线程NioEventLoop中里面有如下几个属性:
1、NioEventLoopGroup (在父类SingleThreadEventExecutor中)
2、selector
3、provider
4、thread (在父类SingleThreadEventExecutor中)
更通俗点就是: NioEventLoopGroup就是一个线程池,NioEventLoop就是一个线程。NioEventLoopGroup线程池中有N个NioEventLoop线程。
ServerBootstrap类分析
本篇博文将分析如下几行代码里面做了些什么。ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new SimpleServerHandler()) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { } });
ServerBootstrap类的继承结构如下:
该类的参数,有必要列出:
private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>(); private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>(); private volatile EventLoopGroup childGroup; private volatile ChannelHandler childHandler;
其父类AbstractBootstrap的参数
private volatile EventLoopGroup group; private volatile ChannelFactory<? extends C> channelFactory; private volatile SocketAddress localAddress; private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>(); private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>(); private volatile ChannelHandler handler;
ServerBootstrap类的无参构造函数什么都没有做,这没什么好说的。下面主要看下这个链式设置相关的参数。
1)group(bossGroup, workerGroup):设置group
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { super.group(parentGroup); if (childGroup == null) { throw new NullPointerException("childGroup"); } if (this.childGroup != null) { throw new IllegalStateException("childGroup set already"); } this.childGroup = childGroup; return this; }
即将workerGroup保存在 ServerBootstrap对象的childGroup属性上。 bossGroup保存在ServerBootstrap对象的group属性上
2)channel(NioServerSocketChannel.class)
public B channel(Class<? extends C> channelClass) { if (channelClass == null) { throw new NullPointerException("channelClass"); } return channelFactory(new BootstrapChannelFactory<C>(channelClass)); } public B channelFactory(ChannelFactory<? extends C> channelFactory) { if (channelFactory == null) { throw new NullPointerException("channelFactory"); } if (this.channelFactory != null) { throw new IllegalStateException("channelFactory set already"); } this.channelFactory = channelFactory; return (B) this; }
函数功能:设置父类属性channelFactory 为: BootstrapChannelFactory类的对象。其中这里BootstrapChannelFactory对象中包括一个clazz属性为:NioServerSocketChannel.class,从如下该类的构造函数中可以明显的得到这一点。
private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> { private final Class<? extends T> clazz; BootstrapChannelFactory(Class<? extends T> clazz) { this.clazz = clazz; } @Override public T newChannel() { try { return clazz.newInstance(); } catch (Throwable t) { throw new ChannelException("Unable to create Channel from class " + clazz, t); } } @Override public String toString() { return StringUtil.simpleClassName(clazz) + ".class"; } }
3)handler(new SimpleServerHandler())
此方法的具体代码如下:
public B handler(ChannelHandler handler) { if (handler == null) { throw new NullPointerException("handler"); } this.handler = handler; return (B) this; }
函数功能:设置handler属性,该属性在其父类 AbstractBootstrap中。
注意:这里的handler函数的入参类是我们自己提供的。如下,后面的博文中将会分析这个handler将会在哪里以及何时被调用,这里只需要记住这一点即可
private static class SimpleServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("channelActive"); } @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("channelRegistered"); } @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { System.out.println("handlerAdded"); } }
4)childHandler
public ServerBootstrap childHandler(ChannelHandler childHandler) { if (childHandler == null) { throw new NullPointerException("childHandler"); } this.childHandler = childHandler; return this; }
简单来说就是将如下的childHandler设置在AbstractBootstrap的相应属性上。
childHandler = new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { } })
总结
比较简单哈,主要是将我们提供的参数设置到其相应的对象属性中去了。 因为后面会用到如下的几个属性,因此最好知道下,这些属性是何时以及在那里赋值的。以免分析到后面会很懵逼。1、group:workerGroup保存在 ServerBootstrap对象的childGroup属性上。 bossGroup保存在ServerBootstrap对象的group属性上
2、channelFactory:BootstrapChannelFactory类的对象(clazz属性为:NioServerSocketChannel.class)
3、handler:SimpleServerHandler
4、childHandler
相关文章推荐
- netty源码分析(三)Netty服务端ServerBootstrap的初始化与反射在其中的应用分析
- Netty 源码分析之 一 服务端创建(ServerBootstrap )
- netty源码学习一(Serverbootstrap引导程序)
- netty4.0.x源码分析—bootstrap
- UiAutomator系列——Appium Server源码分析之作为Bootstrap客户端(011)
- Netty源码分析之Bootstrap启动过程分析
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- Wangle源码分析:ServerBootstrap
- Netty源码分析之一【揭开Bootstrap神秘的红盖头】
- netty(五) NIO创建的TimerServer源码分析之客户端
- Appium Server源码分析之作为Bootstrap客户端
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- netty(四) NIO创建的TimerServer源码分析之服务端
- ServerBootstrap绑定和连接过程源码分析
- Java NIO框架Netty教程(四) – ServerBootStrap启动流程源码分析
- netty4.0.x源码分析—bootstrap
- 【Zookeeper】源码分析之网络通信(三)之NettyServerCnxn
- netty之AbstractBootstrap及其子类源码分析