Netty源码分析(三):客户端操作之发起TCP连接

发起TCP连接

经过Netty源码分析(一):客户端操作之channel()Netty源码分析(二):客户端操作之EventLoopGroup、group()、option()后,
Netty这时候大概初始化结束了,那么客户端是如何发起TCP连接的呢?

在channel方法中,我们调到connect方法会调用initAndRegister,初始化和注册channel,那么完毕且经过一些参数检查之后,最终会调用doConnect方法:

private static void doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise connectPromise) {
	//channel即SocketChannel
    final Channel channel = connectPromise.channel();
    channel.eventLoop().execute(new Runnable() {
        @Override
        public void run() {
            if (localAddress == null) {
                channel.connect(remoteAddress, connectPromise);
            } else {
                channel.connect(remoteAddress, localAddress, connectPromise);
            }
            connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
        }
    });
}

可以看到,此处开启了一个线程来调用connect方法
继续点进去connect,往下走:

AbstractChannel#connect->DefaultChannelPipeline#connect->AbstractChannelHandlerContext#connect
此链调用的是tail.connect方法,即AbstractChannelHandlerContext,因为tail没有实现connect方法:

public ChannelFuture connect(
    final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
    final AbstractChannelHandlerContext next = findContextOutbound();
    EventExecutor executor = next.executor();
    if (executor.inEventLoop()) {
        next.invokeConnect(remoteAddress, localAddress, promise);
    } else {
        safeExecute(executor, new Runnable() {
            @Override
            public void run() {
                next.invokeConnect(remoteAddress, localAddress, promise);
            }
        }, promise, null);
    }
    return promise;
}

此处又开始了一个线程,调用next的invokeConnect方法,最终会找到AbstractNioChannel.AbstractNioUnsafe#connect:

@Override
public final void connect(
    final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
        boolean wasActive = isActive();
        if (doConnect(remoteAddress, localAddress)) {
            fulfillConnectPromise(promise, wasActive);
        } else{}
}

看看doConnect方法:

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);//状态改为connect
        }
        success = true;
        return connected;
    } finally {
        if (!success) {
            doClose();
        }
    }
}

总结一下:
在这里插入图片描述
最后,看看设计时序图:
在这里插入图片描述
NioEventLoop是线程池中的一个线程,重写了这些方法之后,一步步深入操作
NioSocketChannel类似IOC设计,由反射来生成实例
然后就是pipeline,生成一条链,保证执行顺序不会乱;而每个channel都会有单独一个线程来执行,形成并行,并行里的串行则是通过tail和head来控制的
AbstractNioUnsafe则做一下比如线程返回之类的操作
最终就调用了底层的connect方法
都是为了达到异步非阻塞的目的

涉及到装饰器模式、模板模式、责任链模式、工厂模式、反应堆

猜你喜欢

转载自blog.csdn.net/qq_41594698/article/details/89840813