Rust: tokio::io::copy vs io::copy

huangapple go评论77阅读模式
英文:

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::ReadWrite

英文:

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_masterReadWrite 实现会阻塞,那么使用它们会阻塞一个 tokio 任务线程,这并不理想。

解决这个问题的一种方法是将 pty_master 包装在一个类型中,该类型通过在内部使用 spawn_blocking() 来实现 AsyncReadAsyncWrite。 这个代码相当复杂,可能超出了这个网站答案的范围。

英文:

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&lt;R, W&gt;(reader: &amp;mut R, writer: &amp;mut W) -&gt; Result&lt;u64&gt;
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(&amp;mut buf) {
            Ok(n) if n == 0 =&gt; break,
            Ok(n) =&gt; n,
            Err(e) if e.kind() == ErrorKind::Interrupted =&gt; continue,
            Err(e) =&gt; return Err(e),
        };

        len += n as u64;

        writer.write_all(&amp;buf[..n]).await?;
    }

    Ok(len)
}

Warning: You should only use that if your reader is not blocking.

huangapple
  • 本文由 发表于 2023年7月7日 01:48:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631378.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定