Заемные ценности не живут достаточно долго с будущим Токио - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь написать простой HTTP-сервер, используя Rust и Tokio.

Все работает нормально, пока я не хочу отправить ответ.

Код следующий:

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

Как мне объявить ответ достаточно живым?

1 Ответ

1 голос
/ 11 апреля 2019

Как вы можете заставить это работать?

Как я указал в своем комментарии: используйте into_bytes вместо переноса с Arc и передачи массива заимствованных байтов.

Детская площадка


@ Дэвид:

Но я не понимаю, почему завернуть дугой не удалось.

Arc считает ссылку на внутренний объект:

  • увеличивает ссылку, когда вы clone()
  • уменьшает ссылку, когда владелец из Arc удаляется.
  • сбрасывается из памяти, когда счетчик ссылок уменьшается до 0

В вашем случае владелец Arc, который называется response. response создается в области и удаляется в конце той же области. Количество ссылок было 1, когда оно было создано, оно стало 0 после удаления. Но вы передали ссылку Arc внутри Future непосредственно перед тем, как она будет удалена из памяти.

Обратите внимание, что write_all() создает Future и что Future содержит ссылку на ваш Arc, который удаляется из памяти перед выполнением Future.

Примечание : WriteAll может обладать заимствованным или перемещенным значением, он ожидает универсальный параметр, который может быть преобразован в slice.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...