使用Tokio io::split配合Cursor<Vec<u8>>无法读取完整写入数据
问题原因分析
你的问题核心来自两个关键点:
- Cursor的读写位置共享同一指针:
std::io::Cursor的设计是用单个pos值同时标记读、写位置。当你通过WriteHalf写入数据时,pos会被移动到写入后的位置,此时ReadHalf的读操作从当前pos开始,自然读不到之前写入的数据(因为pos已经停在数据末尾)。 - Cursor无异步通知机制:Cursor是纯内存操作,它的
AsyncRead实现不会阻塞等待新数据写入——当当前pos没有可读数据时,会直接返回0(表示EOF),不会等待写任务的写入操作完成。
解决方案
使用Tokio提供的异步双向管道tokio::io::duplex,它专门为异步场景下的生产者-消费者内存通信设计:读端和写端相互独立,写端的数据会被读端正确接收,且读端会阻塞等待新数据,直到写端关闭。
修改后的示例代码:
use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; use tokio::spawn; #[tokio::main] async fn main() { // 创建缓冲区大小为10的异步双向管道 let (mut read, mut write) = io::duplex(10); spawn(async move { for i in 0..10 { write.write_all(&[i]).await.unwrap(); } // 显式关闭写端,让读端知道没有更多数据 drop(write); }); let mut output = vec![]; // read_to_end会持续读取直到写端关闭 read.read_to_end(&mut output).await.unwrap(); assert_eq!(output.len(), 10); }
针对你的实际场景(让函数支持AsyncRead和AsyncWrite),duplex完全适配需求:它返回的读端和写端分别实现了AsyncRead和AsyncWrite,可以直接传递给需要这些 trait 的函数,完美替代Cursor的错误用法。
内容的提问来源于stack exchange,提问作者Jayson Reis
相关产品推荐
相关产品推荐

