英文:
Rust: tokio::io::copy vs io::copy
问题
我试图读写一个支持 tokio::AsyncRead + tokio::AsyncWrite
的流。
问题是,我的另一个流只支持 io::Read + io::Write
。
基本上,我希望像这样做:
let (r, w) = tokio::io::split(async_stream);
tokio::io::copy(pty_master, w);
tokio::io::copy(r, pty_master);
问题是 pty_master
只支持 std::io::Read
和 Write
。
英文:
I am trying to read and write to a stream that support tokio::AsyncRead + tokio::AsyncWrite.
The problem is my other stream only support io::Read + io::Write.
Basically I was hoping to do something like this
Let r, w = tokio::io::split(async_stream);
tokio::io::copy(pty_master, w);
tokio::io::copy(r, pty_master);
Problem is that pty_master only support std::io::Read and Write.
答案1
得分: 1
如果 pty_master
的 Read
和 Write
实现会阻塞,那么使用它们会阻塞一个 tokio 任务线程,这并不理想。
解决这个问题的一种方法是将 pty_master
包装在一个类型中,该类型通过在内部使用 spawn_blocking()
来实现 AsyncRead
和 AsyncWrite
。 这个代码相当复杂,可能超出了这个网站答案的范围。
英文:
If the pty_master
implementations of Read
and Write
block then you'd block a tokio task thread by using them, which is not ideal.
One way to solve this would be to wrap pty_master
in a type that implements AsyncRead
and AsyncWrite
by using spawn_blocking()
under the hood. The code to do this is rather complicated and probably out of the scope of an answer on this site.
答案2
得分: 0
没有内置的功能,但你可以自己编写:
use std::io::{ErrorKind, Read, Result};
use tokio::io::{AsyncWrite, AsyncWriteExt};
// https://github.com/rust-lang/rust/blob/master/library/std/src/sys_common/io.rs#L3C92-L3C92
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
pub async fn copy_half_async<R, W>(reader: &mut R, writer: &mut W) -> Result<u64>
where
R: ?Sized + Read,
W: ?Sized + AsyncWrite + Unpin,
{
let mut buf = vec![0; DEFAULT_BUF_SIZE].into_boxed_slice();
let mut len = 0;
loop {
let n = match reader.read(&mut buf) {
Ok(n) if n == 0 => break,
Ok(n) => n,
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
len += n as u64;
writer.write_all(&buf[..n]).await?;
}
Ok(len)
}
警告: 只有在您的读取器不会阻塞时才应使用此功能。
英文:
There is nothing built-in, but you can write your own:
use std::io::{ErrorKind, Read, Result};
use tokio::io::{AsyncWrite, AsyncWriteExt};
// https://github.com/rust-lang/rust/blob/master/library/std/src/sys_common/io.rs#L3C92-L3C92
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
pub async fn copy_half_async<R, W>(reader: &mut R, writer: &mut W) -> Result<u64>
where
R: ?Sized + Read,
W: ?Sized + AsyncWrite + Unpin,
{
let mut buf = vec![0; DEFAULT_BUF_SIZE].into_boxed_slice();
let mut len = 0;
loop {
let n = match reader.read(&mut buf) {
Ok(n) if n == 0 => break,
Ok(n) => n,
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
len += n as u64;
writer.write_all(&buf[..n]).await?;
}
Ok(len)
}
Warning: You should only use that if your reader is not blocking.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论