Netty4.1源码 :connect & register事件

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}
	}
}	

猜你喜欢

转载自java12345678.iteye.com/blog/2356076