connect事件: Bootstrap b; b.connect(serverIp, port).sync(); | | \|/ javaChannel().register(eventLoop().selector, 0, this); jdk在selector注册channel感兴趣的事件0 | | \|/ 触发添加到channel上的ChannelHandler.handlerAdd方法。 添加源于:Bootstrap b; b.handler(ChannelHandler x) 。 如果是ChannelHandler 是 ChannelInitializer,其initChannel方法内部调用了ch.pipeline().addLast(ChannelHandler added) 则added.handlerAdd 方法被触发 | | \|/ ch.pipeline().fireChannelRegistered()方法被调用: ch.pipeline()中所有ChannelInboundHandler链,从head-->tail顺序依次调用 ((ChannelInboundHandler) handler()).channelRegistered(this); | | \|/ ch.pipeline().connect(remoteAddress, promise);方法被调用: ch.pipeline()中所有ChannelOutboundHandler,从tail-->head顺序依次调用 ((ChannelOutboundHandler) handler()).connect(this, remoteAddress, localAddress, promise);-->直到head。 需要在ChannelOutboundHandler.connect方法中调用:ctx.connect(remoteAddress, localAddress, promise); 来使下一个ChannelOutboundHandler被调用,才能到达head. head中: @Override public void connect( ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception { unsafe.connect(remoteAddress, localAddress, promise);//调用NioSocketChannel.unsafe实现真正我网络连接 } | | \|/ 调用connect返回的ChannelPromise.trySuccess | | \|/ ch.pipeline().fireChannelActive()方法被调用: ch.pipeline()中ChannelInboundHandler链,从head-->tail顺序依次调用 ((ChannelInboundHandler) handler()).channelActive(); ChannelFuture f = b.connect(serverIp, port).sync(); public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> { private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) { final ChannelFuture regFuture = initAndRegister();//创建NioSocketChannel初始化,并注册,将IO线程线程中增加register任务(见下面) final Channel channel = regFuture.channel(); if (regFuture.isDone()) { if (!regFuture.isSuccess()) { return regFuture; } //注册成功后,触发connect事件 return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise()); } else { //注册成功后,触发connect事件(异步) final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel); regFuture.addListener(new ChannelFutureListener() {// @Override public void operationComplete(ChannelFuture future) throws Exception { // Direclty obtain the cause and do a null check so we only need one volatile read in case of a // failure. 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(); doResolveAndConnect0(channel, remoteAddress, localAddress, promise); } } }); return promise; } private static void doConnect( final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise connectPromise) { // This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up // the pipeline in its channelRegistered() implementation. final Channel channel = connectPromise.channel(); channel.eventLoop().execute(new Runnable() {//添加线程任务 @Override public void run() { if (localAddress == null) { channel.connect(remoteAddress, connectPromise); /** 上面这句调用了AbstractChannel * public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { * return pipeline.connect(remoteAddress, promise); * } * ch.pipeline()中所有ChannelOutboundHandler,按非从tail-->head顺序依次调用connect,直到head * ((ChannelOutboundHandler) handler()).connect(this, remoteAddress, localAddress, promise); * head中 * @Override * public void connect( ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception { * unsafe.connect(remoteAddress, localAddress, promise);//调用NioSocketChannel.unsafe实现真正我网络连接 } */ } else { channel.connect(remoteAddress, localAddress, connectPromise); } connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } }); } } protected abstract class AbstractNioUnsafe extends AbstractUnsafe implements NioUnsafe { public final void connect( final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) { try { boolean wasActive = isActive(); if (doConnect(remoteAddress, localAddress)) { //上面方法代码如下: //boolean connected = javaChannel().connect(remoteAddress);//进行网络连接 //if (!connected) {//未连接成功 //selectionKey().interestOps(SelectionKey.OP_CONNECT);//在监听网络连接完成事件,由NioEventLoop类中获取连接成功并处理 //} //success = true; //return connected; // fulfillConnectPromise(promise, wasActive);// //1.触发connect 的ChannelPromise.trySuccess //2.触发 pipeline().fireChannelActive();调用所有 ((ChannelInboundHandler) handler()).channelActive(); } else { //忽略超时处理 } } catch (Throwable t) { promise.tryFailure(annotateConnectException(t, remoteAddress)); closeIfClosed(); } } } protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { if (localAddress != null) { doBind0(localAddress); } boolean success = false; try { boolean connected = javaChannel().connect(remoteAddress); if (!connected) { selectionKey().interestOps(SelectionKey.OP_CONNECT); } success = true; return connected; } finally { if (!success) { doClose(); } } } private void fulfillConnectPromise(ChannelPromise promise, boolean wasActive) { if (promise == null) { // Closed via cancellation and the promise has been notified already. return; } boolean active = isActive(); // trySuccess() will return false if a user cancelled the connection attempt. boolean promiseSet = promise.trySuccess(); // Regardless if the connection attempt was cancelled, channelActive() event should be triggered, // because what happened is what happened. if (!wasActive && active) { pipeline().fireChannelActive(); } // If a user cancelled the connection attempt, close the channel, which is followed by channelInactive(). if (!promiseSet) { close(voidPromise()); } } /** * NioEventLoop内部线程无限循环监控IO事件及执行IO任务。 * 循环内调用processSelectedKeys方法来查找网络事件产生,如connected,read等 * */ public final class NioEventLoop extends SingleThreadEventLoop { private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe(); try { int readyOps = k.readyOps(); if ((readyOps & SelectionKey.OP_CONNECT) != 0) {//如果网络连接成功 int ops = k.interestOps(); ops &= ~SelectionKey.OP_CONNECT; k.interestOps(ops); unsafe.finishConnect();//触发finishConnect方法 } // Process OP_WRITE first as we may be able to write some queued buffers and so free memory. if ((readyOps & SelectionKey.OP_WRITE) != 0) { // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write ch.unsafe().forceFlush(); } if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { unsafe.read(); } } catch (CancelledKeyException ignored) { unsafe.close(unsafe.voidPromise()); } } } register事件:对应jdk的在 selector上注册channel,事件类型为0 javaChannel().register(eventLoop().selector, 0, this(NioSocketChannel)); register事件只发生一次 public abstract class AbstractChannel extends DefaultAttributeMap implements Channel { //AbstractChannel中将 注册任务添加到执行队列,并返回DefaultChannelPromise //ChannelPromise 为DefaultChannelPromise public final void register(EventLoop eventLoop, final ChannelPromise promise) { AbstractChannel.this.eventLoop = eventLoop; if (eventLoop.inEventLoop()) { register0(promise); } else { try { eventLoop.execute(new Runnable() { @Override public void run() { register0(promise); } }); } catch (Throwable t) { //ignore code } } } } protected abstract class AbstractUnsafe implements Unsafe { private void register0(ChannelPromise promise) { try { boolean firstRegistration = neverRegistered; doRegister();//javaChannel().register(eventLoop().selector, 0, this); jdk在selector注册channel感兴趣的事件0 neverRegistered = false; registered = true;//已注册为真 //调用所有ChannelInboundHandlerAdapter.handlerAdded(ChannelHandlerContext ctx) 方法 //ChannelInitializer 就是利用handlerAdded,调用 initChannel(C ch),允许用户实现initChannel,从而对channel初始化 // Bootstrap b.handler( // new ChannelInitializer<SocketChannel>() { // // public void initChannel(SocketChannel ch) throws Exception { // ch.pipeline().addLast(new MyHandler());//此时触发MyHandler的handlerAdded方法 // } // })) // 此时只有ChannelInitializer有一个handler,只有这个ChannelInitializer的handlerAdded被触发 pipeline.invokeHandlerAddedIfNeeded(); safeSetSuccess(promise);//调用promise.trysucess 并触发promise中添加的addListener(GenericFutureListener)监听器 pipeline.fireChannelRegistered();//触发ChannelInboundHandler.channelRegistered方法 // Only fire a channelActive if the channel has never been registered. This prevents firing // multiple channel actives if the channel is deregistered and re-registered. if (isActive()) {//如果网络联通了connected =ture,则触发 channelHandler.channelActive事件 if (firstRegistration) { pipeline.fireChannelActive(); } else if (config().isAutoRead()) { // This channel was registered before and autoRead() is set. This means we need to begin read // again so that we process inbound data. // // See https://github.com/netty/netty/issues/4805 beginRead(); } } } catch (Throwable t) { // Close the channel directly to avoid FD leak. closeForcibly(); closeFuture.setClosed(); safeSetFailure(promise, t); } } } } public abstract class AbstractNioChannel extends AbstractChannel { protected void doRegister() throws Exception { boolean selected = false; for (;;) { try { selectionKey = javaChannel().register(eventLoop().selector, 0, this); return; } catch (CancelledKeyException e) {//ignore} } }
Netty4.1源码 :connect & register事件
猜你喜欢
转载自java12345678.iteye.com/blog/2356076
今日推荐
周排行