问题
I'm trying to write a simple HTTP server using Rust and tokio.
Everything works fine until I want to send the response.
The code is the following:
use std::fs;
use std::sync::Arc;
use tokio::net::TcpListener; // 0.1.15
use tokio::prelude::*;
fn main() {
let addr = "0.0.0.0:8080".parse().unwrap();
let listener = TcpListener::bind(&addr).expect("unable to bind TCP listener");
let incoming = listener.incoming();
let server = incoming
.map_err(|e| eprintln!("accept failed = {:?}", e))
.for_each(|socket| {
println!(
"Connection established: from {:?} to {:?}",
socket.peer_addr(),
socket.local_addr()
);
let bytes = vec![0; 512];
let processor = tokio::io::read(socket, bytes)
.and_then(|(socket, bytes, _size)| {
println!("Request: {}", String::from_utf8_lossy(&bytes[..]));
let contents = fs::read_to_string("hello.html").unwrap();
let response = Arc::new(format!("HTTP/1.1 200 OK\r\n\r\n{}", contents));
let response = response.clone();
tokio::io::write_all(socket, response.as_bytes()).and_then(|_| Ok(()))
})
.map_err(|_| ());
tokio::spawn(processor);
Ok(())
});
tokio::run(server);
}
error[E0597]: `response` does not live long enough
--> src/main.rs:27:50
|
27 | tokio::io::write_all(socket, response.as_bytes()).and_then(|_| Ok(()))
| ^^^^^^^^ borrowed value does not live long enough
28 | })
| - `response` dropped here while still borrowed
How do I have to declare the response to live enough?
回答1:
How can you make it work ?
As i pointed in my comment: use into_bytes
, instead of wrapping with Arc
and passing the borrowed bytes array.
Playground
@David:
But I don't understand why wrapping with arc didn't.
Arc
counts reference of inner object:
- it increases the reference when you
clone()
- it decreases the reference when the owner of
Arc
gets dropped. - it gets dropped from the memory when reference count decreases to 0
In your case owner of the Arc
, which is named as response
. response
is created in scope and dropped at the end of the same scope. It's ref count was 1 when it was created, it became 0 after dropped. But you've passed a reference of Arc
inside a Future
right before it has removed from memory.
Please note that write_all()
creates a Future
and that Future
carries a reference of your Arc
, which is removed from memory before the Future
's execution.
Note: WriteAll
can have ownership of borrowed or moved value it expects a generic parameter which can be converted to a slice
.
来源:https://stackoverflow.com/questions/55610608/borrowed-value-does-not-live-long-enough-with-a-tokio-future