Netty源码之客户端建立与连接

本文深入剖析Netty客户端启动过程,从Bootstrap的connect()方法开始,详细讲解channelFactory().newChannel()、init(channel)以及group().register(channel)的执行逻辑。涉及NioSocketChannel构造、初始化、注册到EventLoopGroup,以及最终的Java NIO SocketChannel的connect方法,阐述客户端如何发起连接请求并等待服务端accept。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

netty引导客户端启动类的代码如下

EventLoopGroup group = new NioEventLoopGroup();
        try {
+            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(
                                    //new LoggingHandler(LogLevel.INFO),
                                    new EchoClientHandler(firstMessageSize));
                        }
                    });

            // Start the client.
            ChannelFuture f = b.connect(host, port).sync();

            // Wait until the connection is closed.
            f.channel().closeFuture().sync();
        } finally {
            // Shut down the event loop to terminate all threads.
            group.shutdownGracefully();
        }

还是老样子,EventLoopGroup,handler这之类的在前几篇博文已经介绍过了,这次就着重跟踪ChannelFuture f = b.connect(host, port).sync(); 这行代码。下面是Boostrap类下的connect()方法:

    public ChannelFuture connect() {
        validate();
        SocketAddress remoteAddress = this.remoteAddress;
        if (remoteAddress == null) {
            throw new IllegalStateException("remoteAddress not set");
        }

        return doConnect(remoteAddress, localAddress());
    }

不得不说跟之前跟踪了的ServerBootstrap.bind()很像。validate()函数无非调用父类AbstractBootstrap的validate()方法,就是检查此Bootstrap对象是否设置了group、channelFactory这两个对象。

然后调用了doConnect创建连接

private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
        final ChannelFuture regFuture = initAndRegister();
        final Channel channel = regFuture.channel();
        if (regFuture.cause() != null) {
            return regFuture;
        }

        final ChannelPromise promise = channel.newPromise();
        if (regFuture.isDone()) {
            doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
        } else {
            regFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
                }
            });
        }

        return promise;
    }

若如果看过我之前服务端的连接,那么看这里肯定会非常亲切熟悉,首先通过initAndRegister()方法得到一个ChannelFuture的实例regFuture,通过regFuture可以看到channel注册过程的状态,通过regFuture.cause()方法判断是否在执行initAndRegister方法时产生来异常,若产生异常则return;最后通过regFuture等channel注册完成,再调用doConnect0();

我们再来具体分析下initAndRegister()这个方法。

    final ChannelFuture initAndRegister() {

        final Channel channel = channelFactory().newChannel();

        try {
            init(channel);
        } catch (Throwable t) {
            channel.unsafe().closeForcibly();
            return channel.newFailedFuture(t);
        }

        ChannelFuture regFuture = group().register(channel);

        if (regFuture.cause() != null) {
            if (channel.isRegistered()) {
                channel.close();
            } else {
                channel.unsafe().closeForcibly();
            }
        }

        return regFuture;
    }
 final Channe
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值