问题
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.
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 (implemented with rustls) allows splitting, but it is relatively new
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).
If I understand correctly, the Tokio/await
paradigm doesn't make sense with the non-blocking sockets. Is my understanding correct?
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.
回答1:
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.
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.
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.
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.
来源:https://stackoverflow.com/questions/61088639/do-i-need-to-move-away-from-tokio-as-i-cannot-split-streams-in-tls-connections