我正在通过 tcp 阅读不同的消息,我的想法是避免将内容复制到内存并重用生成的缓冲区。
我下面显示的代码是我如何通过 tcp 读取的示例。首先,我读取包含要读取的总字节数的标头。然后我创建一个循环来填充设定大小的缓冲区,当达到这个大小时,我创建一条消息并将其发送到另一个线程。在此消息中,我必须执行 .to_vec() 因为我已经确定它是 Vec 类型。一旦它满了,我重置这个缓冲区以继续阅读。AsyncReadExt
如果我将消息中的类型更改为 BytesMut,我会在该行中收到错误:
let mut n_bytes_read = 0;
let mut chunk_id = 0;
let mut last_chunk = false;
// Get header
let total_bytes = stream.read_u32().await.unwrap();
let mut reset = false;
let mut buffer = BytesMut::with_capacity(config.send_buffer_capacity);
let mut bytes_per_chunk = 0;
loop {
if reset {
buffer = BytesMut::with_capacity(config.send_buffer_capacity);
reset = false;
}
match stream.read_buf(&mut buffer).await {
Ok(0) => {
continue;
}
Ok(n) => {
bytes_per_chunk += n;
n_bytes_read += n;
if n_bytes_read == total_bytes.try_into().unwrap() {
last_chunk = true;
}
if bytes_per_chunk == config.send_buffer_capacity || last_chunk{
let message = Message::new(
id,
client_id,
ClientOperation::Send,
chunk_id,
last_chunk,
total_bytes,
buffer.to_vec(),
);
//println!("message: {:?}", message);
queue.push(message);
chunk_id += 1;
bytes_per_chunk = 0;
reset = true;
}
if last_chunk {
break;
}
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
//debug!("Err: TCP -> SV (Write))");
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
如下:
match stream.read_buf(&mut buffer).await {
如果我对缓冲区执行
let mut buffer = BytesMut::with_capacity(config.send_buffer_capacity);
| ---------- move occurs because `buffer` has type `BytesMut`, which does not implement the `Copy` trait
...
402 | loop {
| ---- inside of this loop
...
405 | buffer = BytesMut::with_capacity(config.send_buffer_capacity);
| ------ this reinitialization might get skipped
...
409 | match stream.read_buf(&mut buffer).await {
| ^^^^^^^^^^^ value borrowed here after move
...
430 | buffer,
| ------ value moved here, in previous iteration of loop
,它将执行与执行
.clone()
相同的操作,它将复制内存。然后我必须重置不正常的缓冲区,但什么也不起作用。
我尝试使用
.to_vec()
方法,但它从未写入缓冲区。
有什么方法可以让缓冲区保留在内存中,并且我可以在消息中传递引用吗?并且仍然使用缓冲区继续读取?
read_exact()
而不是跟踪何时并在下一次迭代中执行,则可以避免最简单的问题解决方案。所以从这个最小的复制器开始吧
buffer
对此:
struct Foo;
fn main() {
let mut reset = false;
let mut buffer = Foo;
loop {
if reset {
buffer = Foo;
}
let _message = (buffer,);
reset = true;
}
}