在看完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. mongoDB(3) mapReduce

    mapReduce是大数据的核心内容,但实际操作中别用这个,所谓的mapReduce分两步 1.map:将数据分别取出,Map函数调用emit(key,value)遍历集合中所有的记录,将key与va ...

  2. mongoose index

    1. 当应用程序启动时,Mongoose会自动为模式中的每个定义的索引调用ensureIndex. 虽然很好用于开发,但建议在生产中禁用此行为,因为索引创建可能会导致显着的性能影响. 通过将模式的au ...

  3. php常用方法总结

    /** * created by Tina * time 2015-1-6 10:31 * textarea中传入字符串的处理,返回数组,传入的字符串以换行分割; * 拆分,压缩空格,去除空值,去重复 ...

  4. ubuntu安装eclipse配置jdk环境

    $ sudo mkdir /usr/local/java //在此目录下新建一个文件夹java $ sudo mv 下载/jdk-8u111-linux-i586.tar.gz /usr/local/ ...

  5. SQLite的使用--SQLite语句

    一.SQLite的介绍   1.为什么要存储数据?        1.1 手机数据大多都是从网络加载的,不存储,每次滚动界面都要从新发送网络请求加载数据,浪费流量      1.2 当用户没网的时候, ...

  6. 2Sigma OA prepare: Friends Circle

    DFS & BFS: 关键在于构造graph package twoSigma; import java.util.ArrayList; import java.util.HashSet; i ...

  7. PhoneGap中navigator.notification.confirm的用法详解

    navigator.notification.confirm('您确定要退出程序吗?', showConfirm, '退出程序', '确定,取消'); function showConfirm(but ...

  8. 将java项目转换成Web项目

    http://www.cnblogs.com/kaige123/p/5866446.html 在项目上点击右键,进入Properties配置,点击Project Facets,再点击Convert t ...

  9. OBD K线抓包 III

    14230 HL激活, 5BPS又称 00  //电平激活 C1 33 F1 81 66  //14230的Enter命令 83 F1 11 C1 EF 8F C4 //回应了,一个命令就回应了... ...

  10. TCP/IP 协议介绍

    转自http://blog.jobbole.com/104886/ 一.TCP/IP 协议介绍 在介绍 HTTP 协议之前,先简单说一下TCP/IP协议的相关内容.TCP/IP协议是分层的,从底层至应 ...