如何使用 BufReader 的fill_buff并通过 TcpStream 使用

How do I use BufReader's fill_buff and consume with TcpStream

提问人:andreasppg 提问时间:10/27/2023 更新时间:10/28/2023 访问量:40

问:

以下代码不编译

use std::io::{BufRead, BufReader};
use std::net::{TcpListener};

fn main() {
    let listener = TcpListener::bind(format!("0.0.0.0:{}", 7007)).unwrap();
    for stream in listener.incoming() {
        let mut stream = stream.unwrap();
        let mut buf_reader = BufReader::new(&mut stream);
        let buf = buf_reader.fill_buf().unwrap();
        buf_reader.consume(buf.len())
    }
}

有错误:

error[E0499]: cannot borrow `buf_reader` as mutable more than once at a time
  --> src/main.rs:10:9
   |
9  |         let buf = buf_reader.fill_buf().unwrap();
   |                   --------------------- first mutable borrow occurs here
10 |         buf_reader.consume(buf.len())
   |         ^^^^^^^^^^^^^^^^^^^---------^
   |         |                  |
   |         |                  first borrow later used here
   |         second mutable borrow occurs here

我不明白这与文档示例中使用的代码有何不同

rust 器错误编译 生命周期 borrow-checker

评论

1赞 prog-fh 10/28/2023
将语句拆分为两部分,以便一次只使用一个引用。 然后let amount = buf.len();buf_reader.consume(amount);

答:

1赞 Jared Smith 10/28/2023 #1

该方法采用对结构的可变引用,因此这是一个可变的借用。该方法采用与 does 相同的方法,因此如果编译器认为您仍然坚持使用第一个方法,则不行。fill_bufconsume&mut selffill_buf

在 Rust 中,可变引用是完全排他性的:你不能对同一个内存块持有多个可变引用。

你的代码和文档中的示例之间的区别在于,编译器在文档示例中知道你已经完成了(读取器的第一个可变借用),只要你占用了长度,它就可以释放“锁”,可以说,并在你调用时做好准备。buf.consume

尽管从逻辑上讲,这两者应该是等价的,但请记住,Rust 编译器正在执行所有这些(非常复杂的)静态分析,以既为您管理内存资源,又保证一定程度的线程安全,而无需使用实际的锁,因此它在某种程度上受到源代码文本的限制, 而不是它的逻辑运行时语义。

只需按照 prog-fh 在评论中的建议执行操作,然后拆分调用:.len

let length = buf.len(); // compiler can now drop first mutable borrow because we don't use buf again
buf_reader.consume(length); // second &mut is now exclusive