问题描述
我使用Tokio创建普通的TCP套接字,调用 tokio :: io :: split()
,然后将读/写半部分分配给单独的线程.他们使用带有 await
的异步套接字读/写API来完成IO.我们的数据流在输入/输出方向上是相当隔离的,因此此模型在我们的情况下效果很好.到现在为止还挺好.
I use Tokio to create plain TCP sockets, call tokio::io::split()
and the read/write halves get handed to separate threads. They use the async socket read/write APIs with await
to accomplish the IO. Our data flow is fairly isolated in the in/out directions, so this model works well in our case. So far so good.
现在我正在考虑在顶部添加TLS支持.某些TLS库由于各种原因不允许拆分流:
Now am looking at adding TLS support on top. Some of the TLS libraries don't allow splitting the stream for various reasons:
-
tokio-rustls(用rustls实现)允许拆分,但这是相对较新的
tokio-rustls (implemented with rustls) allows splitting, but it is relatively new
我更喜欢使用tokio-openssl(由openssl实现),它已经存在了很长时间,但是 openssl不支持.这可能是因为像TLS重新协商之类的事件需要传播到读写半部(rustls对其进行管理,因为它是本机Rust实现).
I would prefer to use tokio-openssl (implemented with openssl), which has been around for much longer, but openssl does not support it. This is probably because events like TLS renegotiation need to be propagated to the read/write halves (rustls manages it because it a native Rust implementation).
因此,同一线程需要执行读/写操作.这意味着套接字现在需要变为非阻塞状态:不能等待数据进入,因为可能需要立即发送数据(反之亦然).
So the same thread needs to do the reads/writes. This implies that the socket needs to become non-blocking now: can't wait for data to come in, as data may need to be sent out immediately (and vice versa).
如果我理解正确,那么Tokio/ await
范例对于非阻塞套接字是没有意义的.我的理解正确吗?
If I understand correctly, the Tokio/await
paradigm doesn't make sense with the non-blocking sockets. Is my understanding correct?
在这种情况下,其他任何想法也都欢迎.我希望到目前为止,我们已经付出了所有的努力,而不必放弃Tokio.
Any other ideas in this scenario also welcome. I hope we don't need to abandon Tokio after all the effort put in so far.
推荐答案
的确,异步/等待启用的TLS库,例如 tokio-tls
要求未拆分提供的流,但是一旦将流包装在TLS层中,就可以拆分那个包装的使用 tokio :: io :: split
.
It's true that async/await enabled TLS libraries such as tokio-tls
require the provided stream to not have been split, however once you have wrapped your stream in a TLS layer, you can split that wrapped stream using tokio::io::split
.
以这种方式使用流可以正确处理有关阻塞和非阻塞IO的所有详细信息.由于Tokio的 TcpStream
和 tokio-tls
的 TlsStream
为您处理这些细节.
Using streams in this way correctly handles all details regarding blocking and non-blocking IO. You do not need to manually configure flags such as O_NONBLOCK
, since Tokio's TcpStream
and tokio-tls
's TlsStream
handle these details for you behind the scenes.
使用提供阻止套接字的库自然与Tokio不兼容.这不是什么新事物,并且出于同样的原因,您不能使用 Tokio中的 std :: net :: TcpStream
,因为它是阻塞流.为了避免这些问题,Tokio提供了备用的流类型.
Using a library that provides blocking sockets would naturally not be compatible with Tokio. This is not new, and is for the same reasons that you can't use std::net::TcpStream
within Tokio, as it is a blocking stream. Tokio provides alternate stream types for these purposes to avoid these issues.
如果要使用未启用异步/等待的ssl板条箱,则可以在内存缓冲区中执行加密,并使用Tokio的 TcpStream
手动写入加密数据.启用了async/await的ssl库都以这种方式起作用.
If you wanted to use a non-async/await enabled ssl crate, you can perform the crypto on in-memory buffers, and manually write the encrypted data using Tokio's TcpStream
. The async/await enabled ssl libraries all function in this way.
这篇关于由于无法在TLS连接中拆分流,我是否需要离开Tokio?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!