在看完NIO和SSLEngine集成的例子后,我们了解到并没有提供一个SSLServerSocketChannel,在SelectionKey事件发生后,通过SSLEngine的wrap和unwrap编程实现握手协议。
Tomcat中也是这种做法,我们结合BIO的思路,来看看NIO是怎么做的。

1.SSL环境准备
对于BIO方式的SSL环境的准备,以SSLServerSocket准备好为信号,通过JSSESocketFactory中设置SSLContext,并读取Tomcat的SSL相关配置,最后初始化SSLContext。
NIO的思路也是差不多,也是在NioEndpoint类中:

同样是读取Connector配置的SSLEnabled属性,作为SSL逻辑在NIO通道中的切入点。
对于JSSE实现来讲,SSLUtil实际上就是JSSESocketFactory,只不过NIO通道使用这个接口调用JSSESocketFactory:

在bind方法中,和BIO的逻辑差不多,先读取Keystore的流,然后基于这个对象生成KeyManagerFactory,由KeyManagerFactory 产生KeyManager;对于TrustManager的生成的流程和KeyManager基本类似,最后将两个参数传入SSLContext.init方法中,这样,SSLContext就实例化出来了。
然后,对于Tomcat中配置的选择的SSL协议的版本,和支持的密钥套件进行,和JSSE实现默认支持的,进行取交集:

和BIO也是类似的,这两个属性暂时缓存下来,在Acceptor通道的请求访问的时候,当创建SSLEngine,设置到SSLEngine中。(在BIO是设置到SSLServerSocket中)。

2.SSL请求访问
对于一个请求过来后,SSL的NIO的线程池前面的接收请求还是普通的socket请求没有什么太大的区别,依然是先走Acceptor线程,Acceptor线程建立的SocketChannel,然后包装成PollerEvent,加入到队列中,由Poller线程轮询遍历队列取出PollerEvent,进行selector.select操作,当SelectionKey事件触发后,直接将任务转给工作线程池。

SSL的过程在这个过程中,在Acceptor线程接到数据包后,调用setSocketOptions的属性进行SocketChannel通道的包装:

在包装SocketChannel时,如果是SSL的话,首先,通过SSLContext进行创建SSLEngine,在这个过程中,会将前面缓存下来的Tomcat配置,如已经过滤的协议支持和密码套件支持设置到SSLEngine中,然后创建SecureNioChannel通道,这个SecureNioChannel通道是Acceptor线程专门为SSL交互包装出来的,普通的socket包装的通道是NioChannel,SecureNioChannel继承与NioChannel。

SecureNioChannel的类主要作用就是前面一节中NIO+SSLEngine的思路,主要实现了handshake握手和SSL通道的数据的发送,但是需要值得注意的是,SecureNioChannel类的handshake握手是放在工作线程中的,而Poller线程中读取SelectionKey是在另一个线程中,这相当于有如下的交互方式:

Acceptor线程主要负责数据包读取,当发现新数据来了之后,包装出来一个SocketChannel通道出来,然后注册OP_READ和OP_WRITE事件,这样就相当于上图中的读写通道已经建立完成了。
Poller线程中维护一个Selector,因为读写通道已经建立完毕,所以Poller线程只管监听读写通道发送数据包,如果是普通的socket,Poller线程接收完之后直接会将请求转给工作线程池中的SocketProcessor,后续继续走对应的流程了。

但是对于SSL通道来讲,SecureNioChannel通道中含有SSLEngine,在传输数据之前,需要进行几次的握手,也就是需要像上图一样来回的发送数据,通过wrap进行入栈,通过unwrap进行出栈,一直监测SSLEngineResult.HandShakeStatus的状态,一直到状态是握手成功后,说明由SecureNioChannel已经建立完毕了安全的SSL通道,之后发送的数据同样是使用SecureNioChannel的read和write进行发送,而加密和解密都有SSLEngine的JDK实现来完成。

我们来看看SecureNioChannel通道的切入的位置,在SocketProcessor的工作任务中:

我们看到,工作线程中,是通过handshake的状态进行判断,当handshake=0的时候,握手结束,后续才有handler继续进行处理,当不是0的时候,如果没有遇到异常,需要执行,这一步很关键,也是实现了上面的框图中的Poller线程和工作线程往复交互的行为,将socket和握手状态加入到Poller中,再次关注事件,进行轮询。

最后,再来看看SecureNioChannel类中的handshake实现的内容,基本和前面一节的例子类似:















k.NIO方式SSL通道流程的更多相关文章

  1. i.BIO方式的SSL通道流程

    前面已经讲解了BIO通道的整体流程,对于SSL的流程是插在通道中的,在BIO通道的初始化的时候,根据Connector配置的SSLEnabled属性进行SSL的逻辑. 主要集中的位置在JIOEndpo ...

  2. atitit.ajax bp dwr 3.的注解方式配置使用流程总结 VO9o.....

    atitit.ajax bp dwr 3.的注解方式配置使用流程总结 VO9o..... 1. 安装配置 1 1.1. 下载  dwr.jar 1M 1 1.2. 配置注解方式..web.xml 1 ...

  3. atitit.ajax bp dwr 3.的注解方式配置使用流程总结.....

    atitit.ajax bp dwr 3.的注解方式配置使用流程总结..... 1. 下载  dwr.jar 1M 1 2. 配置注解方式..web.xml 1 3. Class 配置 2 4. 测试 ...

  4. java输入输出 -- java NIO之文件通道

    一.简介 通道是 Java NIO 的核心内容之一,在使用上,通道需和缓存类(ByteBuffer)配合完成读写等操作.与传统的流式 IO 中数据单向流动不同,通道中的数据可以双向流动.通道既可以读, ...

  5. 在Salesforce中通过 Debug Log 方式 跟踪逻辑流程

    在Salesforce中通过 Debug Log方式 跟踪逻辑流程 具体位置如下所示: Setup ---> Logs ---> Debug Logs ---> Monitored ...

  6. 格式化输出的三种方式,运算符及流程控制之if判断

    ''' 格式化输出的三种方式,运算符及流程控制之if判断 ''' # 格式化输出的三种方式 # 一.占位符 程序中经常会有这样场景:要求用户输入信息,然后打印成固定的格式 比如要求用户输入用户名和年龄 ...

  7. java socket编程开发简单例子 与 nio非阻塞通道

    基本socket编程 1.以下只是简单例子,没有用多线程处理,只能一发一收(由于scan.nextLine()线程会进入等待状态),使用时可以根据具体项目功能进行优化处理 2.以下代码使用了1.8新特 ...

  8. SSL握手流程

    一.SSL是什么? 安全套接字(SSL)协议是Web浏览器和Web服务器之间安全交换信息的协议. SSL介于应用层和TCP层之间,应用层数据不再直接传递给传输层,而是传递给SSL层,SSL层对从应用层 ...

  9. JAVA NIO之文件通道

    1.简介 通道是 Java NIO 的核心内容之一,在使用上,通道需和缓存类(ByteBuffer)配合完成读写等操作.与传统的流式 IO 中数据单向流动不同,通道中的数据可以双向流动.通道既可以读, ...

随机推荐

  1. CSS之cssText

    更改元素样式 <div style="width:100px;height:100px;text-align:center;line-height:100px;"> T ...

  2. [BS-31]导航控制器的interactivePopGestureRecognizer属性

    导航控制器的interactivePopGestureRecognizer属性 如何自定义导航控制器push出来的视图控制器的左侧返回按钮? 首先需要知道的是:如果要自定义push出来的VC的左侧返回 ...

  3. Android drawText获取text宽度的三种方式

    String str = "Hello";canvas.drawText( str , x , y , paint); //1. 粗略计算文字宽度Log.d(TAG, " ...

  4. cocos2dx 3.x(定时器或延时动作自动调用button的点击响应事件)实现自动内测

    // // ATTGamePoker.hpp // MalaGame // // Created by work on 2016/11/09. // // #ifndef ATTGamePoker_h ...

  5. Mac下安装UPnP Inspector

    由于工作中需要用到UPnP Inspector这个工具,而这个工具在windows下安装非常简单,在Mac下安装却很麻烦,在此记录安装流程. 这个工具依赖于两个其他的库:Coherence(一个DLN ...

  6. Ant安装、环境变量配置及验证

    一.安装ant 到官方主页http://ant.apache.org下载新版(目前为Ant1.8.1)的ant,得到的是一个apache-ant-1.8.1-bin.zip的压缩包.将其解压到你的硬盘 ...

  7. ThinkPHP讲解(十二)——文本编辑器和ajax传址

    一.文本编辑器 1.首先,在网上下载ueditor文件 2.在要添加文本编辑器的页面中引用ueditor文件中的js文件 <script type="text/javascript&q ...

  8. Using MSBuild to publish a VS 2012 SSDT .sqlproj database project

    http://blog.danskingdom.com/using-msbuild-to-publish-a-vs-2012-ssdt-sqlproj-database-project-the-sam ...

  9. 看门外汉如何实现:C#操作 MongoDB基本CURD的事务控制

    第一部分 基本设计 目前最新版本的C#驱动MongoDB-CSharpDriver-2.2.3,比之前的版本更新比较大,在网上很难找到这个版本的相关C#操作资料,以下都是个人自发研究.测试的,如有雷同 ...

  10. MySQL functions, IF, CASE

    MySQLTutorial官网 IF function syntax: IF(expr,if_true_expr,if_false_expr) CASE expression syntax: CASE ...