bootstrap.connect的调用链路

对于一个 Netty client 来说,在配置好 Bootstrap 之后,通过调用其 connect 方法来连接到远程服务端,如下所示

1
2
3
4
Bootstrap b = new Bootstrap();
b.group(group)
...
ChannelFuture f = b.connect(HOST, PORT).sync();

要完成上述功能,connect 内部需要执行一系列操作

image-20210226012837718

initAndRegister

image-20210226013011247

通过 channelFactory 创建一个 channel 实例。假如 BootStrap 配置 channel 类型为 NioSocketChannel.class,那么就创建一个 NioSocketChannel 类型的实例

1
2
b.group(group)
.channel(NioSocketChannel.class)

init 的实现比较简单,就是对 channelpipeline 进行一些配置

image-20210226013334254

如上图所示,主要进行了这些配置:

  • 往 pipeline 上添加用户自定义的 handler
  • 设置 channel 的选项 option
  • 设置 channel 的属性 attributes

register 的逻辑与 ServerBootStrap 类似,见 注册channel到EventLoop

doResolveAndConnect0

image-20210226014329714

remoteAddress 可能是一个无法解析的地址,所以会先尝试通过 AddressResolver 进行解析。AddressResolverEventLoop 进行关联,通过 map 进行缓存

doConnect

image-20210226015111879

这才到了真正的连接操作

channel.connect -> pipeline.connect -> tail.connect -> ... -> head.connect -> unsafe.connect

unsafe 是一个平台相关的实现类,它依赖于具体的底层实现,例如对于 NioSocketChannel 来说,它的 unsafe 的 connect 方法实现如下图所示

image-20210226015637444

当本地地址不为空时,先要执行 bind 操作,然后再执行 connect 操作

image-20210226015733620

SocketUtils 封装了 jdk 提供的 socket 操作,如下是 connectbind 的实现

image-20210226020016289