netty源码分析之-服务端启动核心源码分析(5)
来源:互联网 发布:淘宝店铺查询 编辑:程序博客网 时间:2024/05/22 03:50
对于netty中服务端启动的核心流程分析
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
/** * Create a new {@link Channel} and bind it. */ public ChannelFuture bind(int inetPort) { return bind(new InetSocketAddress(inetPort)); }
可以追溯到如下具体实现:
private ChannelFuture doBind(final SocketAddress localAddress) { final ChannelFuture regFuture = initAndRegister(); ① final Channel channel = regFuture.channel(); if (regFuture.cause() != null) { return regFuture; } if (regFuture.isDone()) { // At this point we know that the registration was complete and successful. ChannelPromise promise = channel.newPromise(); doBind0(regFuture, channel, localAddress, promise); ② return promise; } else { // Registration future is almost always fulfilled already, but just in case it's not. final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); regFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { Throwable cause = future.cause(); if (cause != null) { // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an // IllegalStateException once we try to access the EventLoop of the Channel. promise.setFailure(cause); } else { // Registration was successful, so set the correct executor to use. // See https://github.com/netty/netty/issues/2586 promise.registered(); doBind0(regFuture, channel, localAddress, promise); } } }); return promise; } }
- ① 对于initAndRegister()方法实现的核心代码:
Channel channel = null;channel = channelFactory.newChannel();init(channel);
channelFactory是AbstractBootstrap中持有的成员变量,是我们之前执行:
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
进行赋值的,也就是调用来之前分析的关于反射的部分,调用默认的无参构造方法生成对象,也就是:
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();...public NioServerSocketChannel() { this(newSocket(DEFAULT_SELECTOR_PROVIDER)); }...private static ServerSocketChannel newSocket(SelectorProvider provider) { try { /** * Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in * {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise. * * See <a href="https://github.com/netty/netty/issues/2308">#2308</a>. */ return provider.openServerSocketChannel(); } catch (IOException e) { throw new ChannelException( "Failed to open a server socket.", e); } }
通过SelectorProvider打开一个SocketChannel通道,openServerSocketChannel是对SocketChannel.open()方法阻塞上的一个优化
对于init(channel)的实现关键代码:
... ChannelPipeline p = channel.pipeline(); ... p.addLast(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } ch.eventLoop().execute(new Runnable() { @Override public void run() { pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } }); ...
该方法主要对ServerBootstrap进行成员变量的一些赋值,同时如果有调用.handle()方法,会在ChannelPipeline后面添加该ChannelInitializer的实现。
- 对于doBind0(regFuture, channel, localAddress, promise)实现:
private static void doBind0( final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) { // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up // the pipeline in its channelRegistered() implementation. channel.eventLoop().execute(new Runnable() { @Override public void run() { if (regFuture.isSuccess()) { channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { promise.setFailure(regFuture.cause()); } } }); }
该方法在channelRegistered触发之前被调用可以去设置pipeline
ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) { if (!future.isSuccess()) { future.channel().close(); } } };
添加的监听器表示当操作结束,但是并不是成功执行完的时候关闭这个Channel。因为这些方法是ChannelFuture.isDone()之后执行的,需要有结束的工作来处理一些资源,采用监听器就能够很好的做到这一点。
阅读全文
0 0
- netty源码分析之-服务端启动核心源码分析(5)
- netty源码分析之服务端启动全
- netty源码分析之服务端
- netty源码分析之服务端启动全解析
- [netty源码分析]--服务端启动的工作流程分析
- netty 服务端发布源码分析
- Netty源码分析:服务端启动全过程(篇幅很长)
- MySQL源码分析及核心内幕之4 -- 源码服务端main函数开始及启动流程
- MySQL源码分析及核心内幕之4 -- 源码服务端main函数开始及启动流程
- Netty 源码分析之 一 服务端创建(ServerBootstrap )
- netty(四) NIO创建的TimerServer源码分析之服务端
- netty(十六)源码分析之服务端创建
- netty源码分析(一)-启动
- 【Netty源码分析】客户端connect服务端过程
- netty源码分析之-ServerBootstrap启动流程分析(3)
- netty源码分析之ChannelFuture
- netty源码分析之ChannelPipeline
- netty源码分析之ChannelHandler
- 《利用python进行数据分析》学习笔记ch09
- mysqldb在python3下无法使用的解决方案
- llinux之管理网络练习
- python简单文本文件读取
- MySQL丢数据及主从数据不一致的场景
- netty源码分析之-服务端启动核心源码分析(5)
- 算法储备之快速排序
- 遇见Laravel Migrations的migrate与rollback
- Android设计模式之装饰模式
- 2017.10.17
- Gradle基础知识——Groovy的闭包
- python3中将`&#x`(《新)的字符串转化为utf-8
- CSRF学习笔记之CSRF的防御
- 提高django性能