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 {
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() {
//
// 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}
}
}