Java NIO2 异步套接字通道/异步服务器套接字通道和 TLS/SSL

11
在互联网上所有的 NIO2 的来源/示例都没有TLS/SSL支持,我理解 SSLEngine 连接生命周期与 AsynchronousSocketChannel.connect && AsynchronousServerSocketChannel.accept 不同。TLS/SSL应该封装在AIO实现内部,那么我该如何同时使用它们呢?注意:我在 Grizzly 项目中看到了一个视频,谈论他们已经实现了它,我看了源代码,但只看到了AIO而没有TLS/SSL集成...提前感谢!

连接的生命周期是一样的:它只是一个连接。但是将 SSLEngine 与非阻塞 NIO 集成的困难程度出于其他原因,例如在应该读取时需要编写,反之亦然,并且如何处理任务:我不喜欢尝试使用异步 I/O 来解决这个问题。 - user207421
刚刚注意到我的悬赏评论中有拼写错误,有人知道如何编辑吗? - Paul Whelan
我应该补充一下我的评论,我随后实现了一个使用SSLEngine的AsyncSSLSocketChannel。正如预料的那样,这并不容易。 - user207421
2个回答

4
原问题的评论确实是正确的。SSLEngine 直接使用 ByteBuffer 进行操作。
这意味着它与AIO兼容。您首先接受连接。然后客户端连接并执行初始写入。要确定是否有足够的数据缓冲,请使用握手状态状态。如果需要从另一端提供更多数据,则引擎将继续告诉您“NEED_UNWRAP”。因此,您需要保留ByteBuffer对象的队列。同样,如果需要在继续之前向另一端发送更多数据,则引擎将继续告诉您“NEED_WRAP”。您需要继续进行,直到从握手状态获得“完成”。
然而,我建议您使用像Netty这样的工具,这将使此过程变得更加简单。值得注意的是,在4的alpha阶段中,Netty确实支持AIO。但是,AIO比NIO更慢,因此被移除了。
然而,Netty不仅会使事情比直接使用NIO或AIO更简单,而且还会使在需要重新引入AIO时轻松切换两者变得容易。
使用Netty进行SSL的完整示例可以在此处找到。

感谢您的输入,我应该指出我知道如何使用SSLEngine,并且已经使用传统的nio实现了一个工作版本。然而,AIO版本让我很难在代码上下功夫。在我的情况下,我想通过自己的方式学习如何实现高效的AIO实现。(我只需要一些关于死锁和在握手期间协调完成处理程序方面的设计指针)。 - Paul Whelan
现在看一下带有AIO的旧版本Netty以获取指针,干杯。 - Paul Whelan
你会发现代码确实是一样的。SSLHandler是一个管道处理程序,无论它是与NIO还是AIO通道工厂一起使用,都是相同的。https://github.com/netty/netty/blob/c149f4bcc0c0d02aa1abcd5e39c155a9e598822e/handler/src/main/java/io/netty/handler/ssl/SslHandler.java - pjulien

2
在Java中进行TLS的标准方法是使用SSLEngine。但是那个类非常难用。虽然有一些教程,但对于典型应用程序来说,使用SSLEngine应该不在考虑范围内。ByteChannel及其相关类没有直接支持,并且意味着需要大量工作。
我曾经遇到过同样的问题,最终编写了自己的库。有一些示例和当然还有像Netty等项目中的代码。但是这两种选择都不够强大或易于重用。 TLS Channel将SSLEngine包装在ByteBuffer中,并允许像普通SocketChannels一样使用它。AsynchronousByteChannels是一个高级抽象层,隐藏了选择器循环;该库也支持此功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接