我的目的是访问TcpStream
并在两个不同的结构方法中执行两次读取操作,该方法将TcpStream
作为属性。
第一个操作执行正常,但是当我尝试在第二个方法上加载剩余的字节时,无法填充缓冲区。
我试图创造一个非常简单的娱乐。这是它的工作原理:
read
和1字节大小的缓冲区读取1个字节。一切都很好。read_exact
和1字节大小的缓冲区读取1个字节。一切都很好。read_exact
对基础read
对象(stream
对象)读取 1字节。缓冲区无法填充。如果我解包,或者带有初始值的缓冲区,我会收到错误。 #[cfg(test)]
mod tests {
use std::net::{TcpListener, TcpStream};
use std::io::{BufReader, Read, Write};
#[test]
fn test_read_twice() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let local_addr = listener.local_addr().unwrap();
let mut stream = TcpStream::connect(local_addr).unwrap();
match listener.accept() {
Ok((mut socket, _)) => {
let _ = socket.write_all(&[0, 1, 2, 4, 5, 7]);
}
Err(e) => println!("couldn't get client: {:?}", e),
}
{
let mut reader = BufReader::new(&mut stream);
let mut buff = vec![0u8; 1];
let _ = reader.read(&mut buff[..]).unwrap();
assert_eq!(buff, vec![0]);
let mut buff = vec![0u8; 1];
let _ = reader.read_exact(&mut buff[..]).unwrap();
assert_eq!(buff, vec![1]);
}
let mut buff = vec![88u8; 1];
let _ = stream.read_exact(&mut buff[..]);
assert_eq!(buff, vec![2]);
}
}
答案 0 :(得分:3)
BufReader
的意思是“提前” - 您只进行了小读取,但BufReader
从底层读取器读取一个大块,将其存储在缓冲区中,并提供服务来自read
的请求。此缓冲区归BufReader
所有 - 当您在底层阅读器上调用read
(或read_exact
)时,您无法从该缓冲区中读取。
由于BufReader
接口没有公开内部缓冲区,因此以后再次使用底层读取器通常没有意义(您无法可靠地进入缓冲区为空的状态)。因此,不要将引用传递给BufReader::new
,而只需按值传递它。通过这种方式,您可以将其永久保留在那里,并在必要时仍然移动BufReader
/ TcpStream
。
如果您需要调用其他(不是Read
相关的)功能(甚至可以通过{{3}取回),您仍然可以通过get_ref
和get_mut
访问基础阅读器},但你会丢失缓冲数据。)