这里调用了反射方法,其实就是将服务端代码中的这一行.channel(NioServerSocketChannel.class)
中的NioServerSocketChannel.class
传入进行对象创建,创建一个NioServerSocketChannel
实例 。
在创建NioServerSocketChannel
的时候,调用了NioServerSocketChannel
的构造方法,构造方法的主要逻辑如下
……public NioServerSocketChannel(SelectorProvider provider, InternetProtocolFamily family) {this(newChannel(provider, family));}public NioServerSocketChannel(ServerSocketChannel channel) {super(null, channel, SelectionKey.OP_ACCEPT);config = new NioServerSocketChannelConfig(this, javaChannel().socket());}private static ServerSocketChannel newChannel(SelectorProvider provider, InternetProtocolFamily family) {……ServerSocketChannel channel =SelectorProviderUtil.newChannel(OPEN_SERVER_SOCKET_CHANNEL_WITH_FAMILY, provider, family);return channel == null ? provider.openServerSocketChannel() : channel;……}……
其中provider.openServerSocketChannel()
就是调用底层 JDK 的 API,获取了 JDK 底层的java.nio.channels.ServerSocketChannel
。
通过super(null, channel, SelectionKey.OP_ACCEPT);
一路跟踪进去,进入AbstractNioChannel
中,
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {super(parent);……ch.configureBlocking(false);……}
关键代码是ch.configureBlocking(false)
,设置 I/O 模型为非阻塞模式 。
通过super(parent)
跟踪上去,
protected AbstractChannel(Channel parent) {this.parent = parent;id = newId();unsafe = newUnsafe();pipeline = newChannelPipeline();}
其中 id 是 Netty 中每条 Channel 的唯一标识 。
以上就是服务端 Channel 的创建过程 。
接下来是服务端 Channel 的初始化过程,回到AbstractBootstrap.initAndResgister()
方法
……final ChannelFuture initAndRegister() {……// channel 的新建channel = channelFactory.newChannel();// channel 的初始化init(channel);……}……
其中的init(channel)
方法就是服务端的 Channel 的初始化过程,Debug 进入,发现是调用了ServerBootstrap.init(channel)
方法,
@Overridevoid init(Channel channel) {……// 设置一些 Channel 的属性和配置信息……p.addLast(new ChannelInitializer<Channel>() {@Overridepublic void initChannel(final Channel ch) {final ChannelPipeline pipeline = ch.pipeline();ChannelHandler handler = config.handler();if (handler != null) {pipeline.addLast(handler);}ch.eventLoop().execute(new Runnable() {@Overridepublic void run() {pipeline.addLast(new ServerBootstrapAcceptor(ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));}});}});}
其核心代码如上,主要用于定义服务端启动过程中需要执行哪些逻辑 。主要分为两块:
- 一块是添加用户自定义的处理逻辑到服务端启动流程 。
- 另一块是添加一个特殊的处理逻辑,ServerBootstrapAcceptor 是一个接入器,接受新请求,把新的请求传递给某个事件循环器 。
@Overrideprotected void doRegister() throws Exception {boolean selected = false;for (;;) {try {selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);return;} catch (CancelledKeyException e) {if (!selected) {// Force the Selector to select now as the "canceled" SelectionKey may still be// cached and not removed because no Select.select(..) operation was called yet.eventLoop().selectNow();selected = true;} else {// We forced a select operation on the selector before but the SelectionKey is still cached// for whatever reason. JDK bug ?throw e;}}}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 原神冒险家试炼第五天怎么过
- 广州怎么去五台山
- 医疗垃圾桶分类五大类
- 五月初五端午节的来历和风俗
- 五年级期待落空的句子
- 剑南春和五粮液哪个好喝_剑南春和五粮液的口感区别
- 骰子五个点怎么玩(骰子五个六五个七怎么玩)
- 五线谱中小音符怎么弹
- 【前端必会】走进webpack生命周期,另类的学习方法
- opencvcv.line