【发布时间】:2020-04-08 08:43:03
【问题描述】:
我使用 Tokio 创建普通的 TCP 套接字,调用 tokio::io::split() 并将读/写部分交给单独的线程。他们使用带有await 的异步套接字读/写API 来完成IO。我们的数据流在输入/输出方向上是相当隔离的,所以这个模型在我们的例子中运行良好。到目前为止,一切都很好。
现在正在考虑在顶部添加 TLS 支持。由于各种原因,一些 TLS 库不允许拆分流:
tokio-rustls(使用 rustls 实现)允许拆分,但相对较新
我更喜欢使用 tokio-openssl(用 openssl 实现),它已经存在了很长时间,但 openssl does not support it。这可能是因为 TLS 重新协商等事件需要传播到读/写部分(rustls 管理它,因为它是原生 Rust 实现)。
所以需要同一个线程进行读/写。这意味着套接字现在需要变为非阻塞:不能等待数据进来,因为数据可能需要立即发送出去(反之亦然)。
如果我理解正确,Tokio/await 范式对非阻塞套接字没有意义。我的理解正确吗?
也欢迎在这种情况下提出任何其他想法。我希望在付出了所有努力之后,我们不需要放弃 Tokio。
【问题讨论】:
-
socket 现在需要变成非阻塞的——它可能已经是非阻塞的了。 Tokio/await 范式不适用于非阻塞套接字——这几乎是整个
async生态系统存在的全部原因:处理非阻塞 IO 更容易推理。你能分享一下你为什么相信相反的观点吗? -
这里的非阻塞是指socket状态:O_NONBLOCK标志。通常的做法是:socket处于阻塞模式,一个
read().await等待数据进来。async系统确保线程在等待时被放弃。但是大多数 r/w 方法都采用&mut self,所以当这个等待处于挂起状态时,不能进行写入。这就是为什么我认为套接字本身需要处于非阻塞模式。如果数据存在而没有实际(异步)阻塞,则这允许“轮询”套接字。希望我回答了你的问题 -
指的是套接字状态:
O_NONBLOCK标志——当然,tokio::net::TcpStream调用mio::net::TcpStream,上面写着:“非阻塞 TCP 流”并且它 @ 987654324@. -
某些 TLS 库由于各种原因不允许拆分流 - 您需要edit 您的问题更具体;理想情况下提供minimal reproducible example。
tokio::io::split只要求底层类型实现AsyncRead+AsyncWrite。我为“tokio tls”找到的第一个搜索结果实现了这两个特征。 -
关于链接线程,它明确表示您可以通过将其放入互斥锁中进行拆分。这基本上就是
tokio::io::split所做的。
标签: asynchronous rust async-await rust-tokio