2017-04-09 2 views
2

Ich versuche, pädagogische Client-Server-Anwendung mit Rust und Eisen zu implementieren. Ich bin auf das Verhalten gestoßen, das ich nicht verstehen kann. Hier ist der Code:Iron :: new() :: http() fängt stdin

fn main() { 
    Iron::new(hello_world).http("localhost:3000").unwrap(); 

    let mut input = String::new(); 
    io::stdin().read_line(&mut input) 
     .expect("Failed to read line"); 

    println!("You entered: {}", &input) 
} 


fn hello_world(_: &mut Request) -> IronResult<Response> { 
    Ok(Response::with((status::Ok, "Hello World!"))) 
} 

Wenn ich es laufen und versuchen, etwas über die Tastatur eingeben, die Linie Sie gemacht haben: Ein Text wird nicht angezeigt.

Aber nachdem ich diese Zeile geändert:

Iron::new(hello_world).http("localhost:3000").unwrap(); 

mit diesem:

let listener = Iron::new(hello_world).http("localhost:3000").unwrap(); 

I String bekam Sie gemacht haben: Einige Text auf meiner Konsole. So scheint es zu funktionieren. Aber jetzt habe ich eine Warnung vor unbenutzter Variable. Dieses Verhalten ist verwirrend.

Kann jemand erklären, warum das tatsächlich passiert?

+1

Denn wenn man den Hörer fallen wird es blockieren bis der Server stirbt, wenn Sie ihn in eine Variable verschieben, wird er blockiert, wenn die Variable gelöscht wird (zB Endsumme) - Sie können die Variable mit "_" voranstellen (l ike '_listener'), um nicht verwendete Warnungen zum Schweigen zu bringen. –

+0

Danke dir. Und danke für den netten Hack mit '_listener'. Ich wusste es nicht. –

Antwort

2

In der ersten Version Ihres Codes blockiert die erste Zeile das Warten auf eingehende Verbindungen. Dies ist, weil die folgenden:

  1. Iron::new(hello_world).http("localhost:3000").unwrap() erzeugt ein Objekt vom Typ Listening, was zu hören http beginnt anfordert in einem separaten Thread. Die Struktur Listening implementiert die Eigenschaft Drop, d. Diese Drop-Funktion wird dem hörenden Thread beitreten, blockiert die weitere Ausführung Ihres Programms.
  2. Indem das Objekt Listening keiner Variablen zugewiesen wird, fällt es sofort aus dem Gültigkeitsbereich. Das bedeutet, dass die drop Funktion direkt nach der Erstellung des Objekts ausgeführt wird.

Alternative Erklärung im Code

Die erste Version des Programms:

fn main() { 
    Iron::new(hello_world).http("localhost:3000").unwrap(); 
    // The listening thread is joined here, so the program blocks 
    // The instructions below will never be executed 

    let mut input = String::new(); 
    io::stdin().read_line(&mut input) 
     .expect("Failed to read line"); 

    println!("You entered: {}", &input) 
} 

Die Ergebnisse einer variablen Einführung:

fn main() { 
    let listener = Iron::new(hello_world).http("localhost:3000").unwrap(); 

    let mut input = String::new(); 
    io::stdin().read_line(&mut input) 
     .expect("Failed to read line"); 

    println!("You entered: {}", &input) 

    // The listening thread is joined here, so the program blocks 
    // As you can see, the program will not exit 
} 
+0

Danke für die gründliche Erklärung! Hat dieses Muster einen Namen in Rust? –

+0

Ich meine, ist es eine gängige Praxis, dies zu tun? –

+0

Dies ist ein übliches Muster, nicht nur in Rust. C++ hat beispielsweise Destruktoren, die auch ausgeführt werden, wenn ein Objekt außerhalb des Gültigkeitsbereichs liegt. Sie können mehr über 'Drop' im [Rust Book] lesen (https://doc.rust-lang.org/nightly/book/first-edition/drop.html) – aochagavia