上一篇博客【Netty源码分析】Netty服务端bind端口过程 我们介绍了服务端绑定端口的过程,这一篇博客我们介绍一下客户端连接服务端的过程。

ChannelFuture future = boostrap.connect("127.0.0.1", 8080).sync();  

调用BootStrap的connect函数

public ChannelFuture connect(String inetHost, int inetPort) {
        return connect(InetSocketAddress.createUnresolved(inetHost, inetPort));
}
public ChannelFuture connect(SocketAddress remoteAddress) {
        if (remoteAddress == null) {
            throw new NullPointerException("remoteAddress");
        }

        validate();
        return doResolveAndConnect(remoteAddress, config.localAddress());
    }

调用doResolveAndConnect函数

 private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
    ........
    return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise());
    ........
}
private ChannelFuture doResolveAndConnect0(final Channel channel, SocketAddress remoteAddress,
                                               final SocketAddress localAddress, final ChannelPromise promise)
	........

    doConnect(remoteAddress, localAddress, promise);

	........

}

调用doConnect函数时会同时开启一个线程,用来处理客户端的操作。

 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);
                } else {
                    channel.connect(remoteAddress, localAddress, connectPromise);
                }
                connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            }
        });
    }

AbstractChannel的connect函数

@Override
public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        return pipeline.connect(remoteAddress, localAddress, promise);
}
@Override
public final ChannelFuture connect(
            SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        return tail.connect(remoteAddress, localAddress, promise);
}
private void invokeConnect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        if (invokeHandler()) {
            try {
                ((ChannelOutboundHandler) handler()).connect(this, remoteAddress, localAddress, promise);
            } catch (Throwable t) {
                notifyOutboundHandlerException(t, promise);
            }
        } else {
            connect(remoteAddress, localAddress, promise);
        }
    }

HeadContext的connect函数

@Override
public void connect(
                ChannelHandlerContext ctx,
           SocketAddress remoteAddress, SocketAddress localAddress,
                ChannelPromise promise) throws Exception {
  unsafe.connect(remoteAddress, localAddress, promise);
}

AbstractUnsafe函数的connect函数

@Override
public final void connect(
                final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
    .......

    if (doConnect(remoteAddress, localAddress)) {
        fulfillConnectPromise(promise, wasActive);
    }

	.......
}

调用NioSocketChannle的doConnect函数

 @Override
    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();
            }
        }
    }

或许执行doBind0函数

private void doBind0(SocketAddress localAddress) throws Exception {
        if (PlatformDependent.javaVersion() >= 7) {
            javaChannel().bind(localAddress);
        } else {
            javaChannel().socket().bind(localAddress);
        }
    }

javaChannle()函数获得的就是SocketChannle对象,这样就完成了客户端连接服务端的操作。

【Netty源码分析】客户端connect服务端过程的更多相关文章

  1. Netty 源码(一)服务端启动

    Netty 源码(一)服务端启动 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) ServerBootstap 创建时序图如 ...

  2. Netty源码分析 (七)----- read过程 源码分析

    在上一篇文章中,我们分析了processSelectedKey这个方法中的accept过程,本文将分析一下work线程中的read过程. private static void processSele ...

  3. Fresco 源码分析(三) Fresco服务端处理(1) ImagePipeline为何物

    4.3 服务端的处理 备注: 因为是分析,而不是设计,所以很多知识我们类似于插叙的方式叙述,就是用到了哪个知识点,我们再提及相关的知识点,如果分析到了最后,我想想是不是应该将这个架构按照设计的方式,重 ...

  4. Fresco 源码分析(三) Fresco服务端处理(2) Producer具体实现的内容

    我们以mProducerFactory.newNetworkFetchProducer()为例,因为这些创建新的producer的方式类似,区别在于是否有包装的处理器,即如果当前处理器中没有正在处理的 ...

  5. (二)Netty源码学习笔记之服务端启动

    尊重原创,转载注明出处,原文地址:http://www.cnblogs.com/cishengchongyan/p/6129971.html  本文将不会对netty中每个点分类讲解,而是一个服务端启 ...

  6. Fresco 源码分析(三) Fresco服务端处理(3) DataSource到Producer的适配器逻辑以及BitmapMemoryCacheProducer处理的逻辑

    4.3.1.2.1 Producer和DataSource之间适配器处理的逻辑 还是从程序的入口开始说吧 CloseableProducerToDataSourceAdapter.create() 源 ...

  7. Netty源码分析 (八)----- write过程 源码分析

    上一篇文章主要讲了netty的read过程,本文主要分析一下write和writeAndFlush. 主要内容 本文分以下几个部分阐述一个java对象最后是如何转变成字节流,写到socket缓冲区中去 ...

  8. 【Netty源码分析】发送数据过程

    前面两篇博客[Netty源码分析]Netty服务端bind端口过程和[Netty源码分析]客户端connect服务端过程中我们分别介绍了服务端绑定端口和客户端连接到服务端的过程,接下来我们分析一下数据 ...

  9. Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化

    Netty源码分析第一章:  Server启动流程 概述: 本章主要讲解server启动的关键步骤, 读者只需要了解server启动的大概逻辑, 知道关键的步骤在哪个类执行即可, 并不需要了解每一步的 ...

随机推荐

  1. codeforces 842C Ilya And The Tree

    Ilya is very fond of graphs, especially trees. During his last trip to the forest Ilya found a very ...

  2. NOIWC2018 游记

    day1 上午是自习,做了一些杂题,看了一下ppt,中午准备了一下行李,就出发了,提前了一个小时,谁知道被坑爹导航弄得居然到晚了一点 当走到这里的时候我愣住了 纠结了一分钟,直到有个boy走了进去,我 ...

  3. hdu 5895 广义Fibonacci数列

    Mathematician QSC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  4. [APIO2014]

    T1.回文树裸题. #include<cstdio> #include<iostream> #define ll long long using namespace std; ...

  5. Windows下使用notepad++对文本进行行列转换

    行转列: Ctrl + F  选择替换 查找目标:填写指定的内容 替换为:\r\n 查找模式:正则表达式 单击替换或全部替换按钮 列转行: Ctrl + F  选择替换 查找目标:\r\n 替换为:不 ...

  6. mac下IDLE无法输入中文的问题

    解决方法是下载安装新版本的 Tcl/Tk 下载地址:http://www.activestate.com/activetcl/downloads 注意要下最新的8.5.18.0版本,安装好了再重启ID ...

  7. 获取X天后的日期

    import java.util.Calendar; import java.util.Date; public class main { public static void main(String ...

  8. org.apache.maven.archiver.MavenArchiver.getManifest

    eclipse导入新的maven项目时,pom.xml第一行报错: org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.mav ...

  9. 使用redis做缓存

    redis常本用来作为缓存服务器.缓存的好处是减少服务器的压力,数据查询速度快.解决数据响应慢的问题. 添加缓存:只用redis的Hash数据类型添加缓存. 例如:需要在查询的业务功能中,添加缓存 1 ...

  10. centos6.8下weblogic12c静默安装

    环境: centos6.8 无桌面环境 jdk1.7.0_25 关闭iptables.selinux 安装前准备: 1.新建weblogic用户,设置weblogic密码 useradd weblog ...