Netty源码分析(三):客户端启动
Bootstrap
Bootstrap主要包含两个部分,一个是服务器地址的解析器组AddressResolverGroup,另一个是用来工作的EventLoopGroup。
EventLoopGroup负责出人EventLoop,AddressResolverGroup负责给EventLoop解析服务器地址。
客户端连接远程服务器
连接远程服务器,会先check引导类(Bootstrap)的group有没有设置以及生成channel的工厂,之后再调用doResolveAndConnect方法。
private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
// 初始化并注册一个channel,并将chanelFuture返回
final ChannelFuture regFuture = initAndRegister();
// 得到实际的channel(初始化和注册的动作可能尚未完成)
final Channel channel = regFuture.channel();
// 当到这chanel相关处理已经完成时
if (regFuture.isDone()) {
// 连接失败直接返回
if (!regFuture.isSuccess()) {
return regFuture;
}
// 解析服务器地址并完成连接动作
return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise());
} else {
// 注册一般到这就已经完成,这里以防万一
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
// 添加一个监听器
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
// Directly obtain the cause and do a null check so we only need one volatile read in case of a
// failure.
Throwable cause = future.cause();
if (cause != null) {
promise.setFailure(cause);
} else {
// 修改注册状态为成功(当注册成功时不在使用全局的executor,使用channel自己的,详见 https://github.com/netty/netty/issues/2586)
promise.registered();
// 进行相关的绑定操作
doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
}
}
});
return promise;
}
}
和ServerBootstrap一样,Bootstrap也要先去初始化和注册channel,注册的方法和ServerBootstrap相同,初始化channel的方法有所区别。
初始化channel
void init(Channel channel) throws Exception {
ChannelPipeline p = channel.pipeline();
p.addLast(config.handler());
// 获取channel的可选项Map
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
setChannelOptions(channel, options, logger);
}
// 获取channel的属性Map
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e : attrs.entrySet()) {
channel.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
}
}
客户端channel的初始化和服务端相比要简单很多,只需要设置一些相关信息即可。
channel处理好之后,客户端就会去连接服务器。
连接服务器
private ChannelFuture doResolveAndConnect0(final Channel channel, SocketAddress remoteAddress,
final SocketAddress localAddress, final ChannelPromise promise) {
try {
final EventLoop eventLoop = channel.eventLoop();
final AddressResolver<SocketAddress> resolver = this.resolver.getResolver(eventLoop);
// 解析器不知道怎么处理这个服务器地址或者已经处理过了
if (!resolver.isSupported(remoteAddress) || resolver.isResolved(remoteAddress)) {
doConnect(remoteAddress, localAddress, promise);
return promise;
}
// 解析服务器地址
final Future<SocketAddress> resolveFuture = resolver.resolve(remoteAddress);
// 解析完成时
if (resolveFuture.isDone()) {
final Throwable resolveFailureCause = resolveFuture.cause();
if (resolveFailureCause != null) {
// 解析失败直接关闭channel
channel.close();
promise.setFailure(resolveFailureCause);
} else {
// 解析成功开始连接
doConnect(resolveFuture.getNow(), localAddress, promise);
}
return promise;
}
// 解析没完成时等待解析完成
resolveFuture.addListener(new FutureListener<SocketAddress>() {
@Override
public void operationComplete(Future<SocketAddress> future) throws Exception {
if (future.cause() != null) {
// 解析失败直接关闭channel
channel.close();
promise.setFailure(future.cause());
} else {
// 解析成功开始连接
doConnect(future.getNow(), localAddress, promise);
}
}
});
} catch (Throwable cause) {
promise.tryFailure(cause);
}
return promise;
}
当服务器地址是IP的时候,直接连接,如果是域名之类的,会先解析出服务器的IP地址,然后再进行连接。域名解析直接使用的java.net.InetAddress的getByName方法,而连接的方法调用的是sun.nio.ch.SocketChannelImpl的connect方法。
文中帖的代码注释全在:https://github.com/KAMIJYOUDOUMA/nettyForAnalysis.git , 有兴趣的童鞋可以关注一下。
本篇到此结束,如果读完觉得有收获的话,欢迎点赞、关注、加公众号【贰级天災】,查阅更多精彩历史!!!
Netty源码分析(三):客户端启动的更多相关文章
- Netty源码分析之客户端启动过程
一.先来看一下客户端示例代码. public class NettyClientTest { public void connect(int port, String host) throws Exc ...
- Netty源码分析-- 处理客户端接入请求(八)
这一节我们来一起看下,一个客户端接入进来是什么情况.首先我们根据之前的分析,先启动服务端,然后打一个断点. 这个断点打在哪里呢?就是NioEventLoop上的select方法上. 然后我们启动一个客 ...
- 【Netty源码分析】客户端connect服务端过程
上一篇博客[Netty源码分析]Netty服务端bind端口过程 我们介绍了服务端绑定端口的过程,这一篇博客我们介绍一下客户端连接服务端的过程. ChannelFuture future = boos ...
- Netty源码分析之服务启动
本节主要分析server的启动过程. Netty是基于Nio实现的,所以也离不开selector.serverSocketChannel.socketChannel和selectKey等,只不过Net ...
- 【Netty源码分析】发送数据过程
前面两篇博客[Netty源码分析]Netty服务端bind端口过程和[Netty源码分析]客户端connect服务端过程中我们分别介绍了服务端绑定端口和客户端连接到服务端的过程,接下来我们分析一下数据 ...
- Netty源码分析 (三)----- 服务端启动源码分析
本文接着前两篇文章来讲,主要讲服务端类剩下的部分,我们还是来先看看服务端的代码 /** * Created by chenhao on 2019/9/4. */ public final class ...
- Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化
Netty源码分析第一章: Server启动流程 概述: 本章主要讲解server启动的关键步骤, 读者只需要了解server启动的大概逻辑, 知道关键的步骤在哪个类执行即可, 并不需要了解每一步的 ...
- Netty源码分析第3章(客户端接入流程)---->第1节: 初始化NioSockectChannelConfig
Netty源码分析第三章: 客户端接入流程 概述: 之前的章节学习了server启动以及eventLoop相关的逻辑, eventLoop轮询到客户端接入事件之后是如何处理的?这一章我们循序渐进, 带 ...
- Netty源码分析第3章(客户端接入流程)---->第4节: NioSocketChannel注册到selector
Netty源码分析第三章: 客户端接入流程 第四节: NioSocketChannel注册到selector 我们回到最初的NioMessageUnsafe的read()方法: public void ...
- Netty源码分析第1章(Netty启动流程)---->第2节: NioServerSocketChannel的创建
Netty源码分析第一章: Server启动流程 第二节:NioServerSocketChannel的创建 我们如果熟悉Nio, 则对channel的概念则不会陌生, channel在相当于一个通 ...
随机推荐
- python编程之如何在Windows上安装python
一.安装python 首先检查你的系统里是否安装了python,开始菜单里点击运行输入cmd打开一个命令窗口,或键盘快捷键windows+R打开,在窗口中输入python并回车,如果出现了Python ...
- JAVA的环境变量配置
开发JAVA程序需要先准备开发环境,安装好操作系统后首先需要去下载JDK并安装. JDk(Java Development Kit )是Java开发工具包,如果您要开发基于Java的应用首先需要下载并 ...
- 2019.03.11 bzoj4813: [Cqoi2017]小Q的棋盘(贪心)
传送门 考虑最后所有走过的点构成的树,显然除了最长链走一遍以外每条轻链都走两遍. 于是求一波最长链搞一搞就完了. 注意几个小细节特判qwq 代码: #include<bits/stdc++.h& ...
- Ramnit 蠕虫分析
0x00前言 Ramnit 蠕虫是一种通过可移动驱动器传播的蠕虫.该蠕虫还可以作为后门,允许远程攻击者访问受感染的计算机,通常会寄生在用户的浏览器中,难以察觉,因此每天都有数以万计的用户受其困扰. 分 ...
- PHP中this,self,parent的区别
{一}PHP中this,self,parent的区别之一this篇 面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行P ...
- Xaml引用图片路径的方式
最近写代码的时候遇到过好几次引用某个路径下图片资源的情况,思索了一下,便将自己所知的在xaml里引用图片资源的方法写成了个小Demo,并完成了这篇博文.希望罗列出的这些方式能够对大家有所帮助. Xam ...
- poj 1050 最大子矩阵
a11 a12 a13 a14 a15 a21 a22 a23 a24 a25 a31 a32 a33 a34 a35 a41 a42 a43 ...
- WPF 开发备忘录
运营日: select t.* from (select ab.*, bs.station_cn_name, bd.device_name from audit_tvm_cas ...
- java web spring 发送邮件
package com.ws.common.mail; import java.io.File; import javax.mail.internet.MimeMessage; import java ...
- 在windows上安装wamp时遇到apache无法启动,图标为橙色
1.首先测试端口号是否被占用,如果端口号被占用,修改相对应文件的端口号,修改端口号的方法网上很容易搜到. 2.如果端口号没有被占用,cd到httpd.exe目录下,查看错误原因,这里我显示的错误是ht ...