在看完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. iOS: 上传App到AppStore,由于Xcode上传太慢,换成Application Loader上传,速度秒传

    一.遇到的遭遇 在之前的项目开发中,本人有点固执,一直采用xcode打包后再上传,结果可想而知: (1)要么上传时速度慢的跟蜗牛似的,等的我心力交瘁(不排除网络不给力的原因,公司这个吊问题快把我气疯了 ...

  2. zabbix调用微信报警

    1.注册微信企业号,可以选团体号(针对小团队) 2.创建管理组 3.创建部门,记住部门id (使用了部门id,发消息会发送到所有部门成员,所以如果要单独发送给某个用户,""这样设置 ...

  3. Cross-site Scripting (XSS) 阅读笔记

    本文源自 https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29 通过阅读和翻译,并按照自己的理解,整理成如下文档. 概述 XSS ...

  4. [转] 基于MySQL的秒杀核心设计(减库存部分)-防超卖与高并发

    商品详情页面的静态化,varnish加速,秒杀商品库独立部署服务器这种就略过不讲了.只讨论库存部分的优化 mysql配置层面的优化可以参考我的这篇文章 <关于mysql innodb引擎性能优化 ...

  5. IOS asc码替换

    -(void)click:(UIButton *)btn { NSString *testStr = @"学>与全等"; NSStringEncoding encoding2 ...

  6. 欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去

    写诗或者写程序的时候,我们经常要跟欧几里得算法打交道.然而有没要考虑到为什么欧几里得算法是有效且高效的,一些偏激(好吧,请允许我用这个带有浓重个人情感色彩的词汇)的计算机科学家认为,除非程序的正确性在 ...

  7. cell长按出错

    错误的原因: *** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reaso ...

  8. 最长公共子序列(加强版) Hdu 1503 Advanced Fruits

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  9. C# 中using的几个用途

    参考文献 http://www.cnblogs.com/morningwang/archive/2008/03/12/1102952.html http://msdn.microsoft.com/zh ...

  10. Bug测试报告--连连看——天天向上

    测试时间:2016-11-23 20:10 测试者:刘芳芳(nice!团队) 代码地址:HTTPS:https://git.coding.net/jx8zjs/llk.git SSH:git@git. ...