Netty源码分析之建立连接(下)

服务端接收处理器专门针对客户端连接请求做了处理,往新建客户端通道的管道中添加服务端刚开始设置的子处理器,把对应的网络选项以及参数设置到配置中,最后从子线程组中挑选一个线程注册到客户端通道上,专门用于与客户端进行网络交互

private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    final Channel child = (Channel) msg;

    child.pipeline().addLast(childHandler);

    setChannelOptions(child, childOptions, logger);

    for (Entry<AttributeKey<?>, Object> e: childAttrs) {
        child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
    }

    try {
        childGroup.register(child).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (!future.isSuccess()) {
                    forceClose(child, future.cause());
                }
            }
        });
    } catch (Throwable t) {
        forceClose(child, t);
    }
}

处理完请求后释放缓存,进而激活通道读完成操作

private final List<Object> readBuf = new ArrayList<Object>();
try {
    readBuf.clear();
    pipeline.fireChannelReadComplete();

    if (exception != null) {
        closed = closeOnReadError(exception);

        pipeline.fireExceptionCaught(exception);
    }

    if (closed) {
        if (isOpen()) {
            close(voidPromise());
        }
    }
} finally {
    // Check if there is a readPending which was not processed yet.
    // This could be for two reasons:
    // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
    // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
    //
    // See https://github.com/netty/netty/issues/2254
    if (!config.isAutoRead() && !isReadPending()) {
        removeReadOp();
    }
}

从头结点开始触发

public final ChannelPipeline fireChannelReadComplete() {
    AbstractChannelHandlerContext.invokeChannelReadComplete(head);
    return this;
}

static void invokeChannelReadComplete(final AbstractChannelHandlerContext next) {
    EventExecutor executor = next.executor();
    if (executor.inEventLoop()) {
        next.invokeChannelReadComplete();
    } else {
        Runnable task = next.invokeChannelReadCompleteTask;
        if (task == null) {
            next.invokeChannelReadCompleteTask = task = new Runnable() {
                @Override
                public void run() {
                    next.invokeChannelReadComplete();
                }
            };
        }
        executor.execute(task);
    }
}

依次进行处理,头处理器依然是触发通道读操作,这次因为已经在监听链接事件了,所以只是把准备读设置为true


private void invokeChannelReadComplete() {
    if (invokeHandler()) {
        try {
            ((ChannelInboundHandler) handler()).channelReadComplete(this);
        } catch (Throwable t) {
            notifyHandlerException(t);
        }
    } else {
        fireChannelReadComplete();
    }
}

public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    ctx.fireChannelReadComplete();
    readIfIsAutoRead();
}

依次触发流入类型的处理器的读完成操作。


public ChannelHandlerContext fireChannelReadComplete() {
    invokeChannelReadComplete(findContextInbound());
    return this;
}

客户端建立连接成功

 

客户端监听的是连接事件,获取连接后清除连接关注点

public final class NioEventLoop extends SingleThreadEventLoop

// We first need to call finishConnect() before try to trigger a read(...) or write(...) as otherwise
// the NIO JDK channel implementation may throw a NotYetConnectedException.
if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
    // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
    // See https://github.com/netty/netty/issues/924
    int ops = k.interestOps();
    ops &= ~SelectionKey.OP_CONNECT;
    k.interestOps(ops);

    unsafe.finishConnect();
}

触发完成连接的建立    

public final void finishConnect() {
    // Note this method is invoked by the event loop only if the connection attempt was
    // neither cancelled nor timed out.

    assert eventLoop().inEventLoop();

    try {
        boolean wasActive = isActive();
        doFinishConnect();
        fulfillConnectPromise(connectPromise, wasActive);
    } catch (Throwable t) {
        fulfillConnectPromise(connectPromise, annotateConnectException(t, requestedRemoteAddress));
    } finally {
        // Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used
        // See https://github.com/netty/netty/issues/1770
        if (connectTimeoutFuture != null) {
            connectTimeoutFuture.cancel(false);
        }
        connectPromise = null;
    }
}

再次检验链接是否建立


protected void doFinishConnect() throws Exception {
    if (!javaChannel().finishConnect()) {
        throw new Error();
    }
}

通知超时等待的链接建立的Promise,设置成功状态,激活客户端通道活跃事件,头结点处理器处理完该事件后更改网络关注点为初始设置的读事件关注点,设置准备读的状态为true,最后取消链接超时检测的Future。

private void fulfillConnectPromise(ChannelPromise promise, boolean wasActive) {
    if (promise == null) {
        // Closed via cancellation and the promise has been notified already.
        return;
    }

    // Get the state as trySuccess() may trigger an ChannelFutureListener that will close the Channel.
    // We still need to ensure we call fireChannelActive() in this case.
    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());
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值