Learn Rust Coding · Lekcja

Tworzenie aplikacji asynchronicznych za pomocą Tokio

Nauczą się Państwo używać runtime’u Tokio do wydajnego wykonywania zadań asynchronicznych oraz obsługi operacji wejścia-wyjścia i innych operacji współbieżnych.

Lekcja 2 z 311 kroki

Tworzenie aplikacji asynchronicznych za pomocą Tokio to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 2 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 3 lekcji w sumie.

Poznajemy środowisko uruchomieniowe Tokio

Witamy ponownie! W poprzedniej lekcji poznali Państwo elementy async i await. Ale jak właściwie uruchamiana jest funkcja async?

Właśnie tutaj przydaje się asynchroniczne środowisko uruchomieniowe, takie jak Tokio. Tokio to zaawansowana biblioteka udostępniająca środowisko wykonywania asynchronicznego kodu Rust.

  • Planuje i wykonuje obiekty typu Future.
  • Obsługuje nieblokujące operacje wejścia-wyjścia.
  • Efektywnie zarządza współbieżnymi zadaniami.

Uruchamianie kodu asynchronicznego

Aby rozpocząć pracę z Tokio, zwykle używa się makra atrybutu #[tokio::main]. To makro przekształca funkcję async fn main() w standardową funkcję fn main(), która inicjalizuje środowisko uruchomieniowe Tokio i wykonuje kod asynchroniczny.

Można traktować je jako punkt wejścia aplikacji asynchronicznej.

use tokio;

#[tokio::main]
async fn main() {
  println!("Hello from Tokio!");
}

Tworzenie nowych zadań asynchronicznych

Jedną z podstawowych funkcji Tokio jest możliwość równoczesnego wykonywania wielu operacji asynchronicznych. Można to osiągnąć za pomocą tokio::spawn.

tokio::spawn przyjmuje obiekt typu Future i planuje jego wykonanie w środowisku uruchomieniowym Tokio. Dzięki temu główne zadanie może dalej działać, podczas gdy utworzone zadanie wykonuje się w tle.

  • Nie blokuje wykonywania.
  • Zwraca obiekt JoinHandle, którego można użyć do oczekiwania na zakończenie zadania.
  • Zadania działają niezależnie.

<code>tokio::spawn</code> w praktyce

Zobaczmy, jak tokio::spawn pozwala wykonywać kod współbieżnie. Proszę zauważyć, że pojawiają się oba komunikaty, ale komunikat „done” może zostać wyświetlony przed komunikatem „task complete” z powodu uśpienia.

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  // Spawn a new task
  let handle = tokio::spawn(async {
    sleep(Duration::from_secs(1)).await;
    println!("Async task complete!");
  });

  println!("Main task continuing...");

  // Wait for the spawned task to finish
  handle.await.unwrap();
  println!("All tasks done.");
}

Oczekiwanie na wiele zadań

Gdy mają Państwo wiele zadań, często trzeba zaczekać na zakończenie wszystkich z nich. Tokio udostępnia do tego celu makro tokio::join!.

tokio::join! pozwala współbieżnie oczekiwać na wiele obiektów typu Future i połączyć ich wyniki. Działa podobnie do oczekiwania za pomocą `await` na wielu obiektach `JoinHandle`, ale często jest bardziej zwięzłe w przypadku stałego zestawu obiektów typu Future.

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  let task1 = async {
    sleep(Duration::from_secs(1)).await;
    println!("Task 1 finished");
    1
  };

  let task2 = async {
    sleep(Duration::from_millis(500)).await;
    println!("Task 2 finished");
    2
  };

  let (result1, result2) = tokio::join!(task1, task2);
  println!("Results: {}, {}", result1, result2);
}

Asynchroniczne operacje na plikach za pomocą Tokio

Tradycyjne operacje na plikach mogą blokować wątek, co jest niekorzystne w aplikacjach asynchronicznych. Moduł tokio::fs biblioteki Tokio udostępnia asynchroniczne wersje operacji na systemie plików.

Dzięki temu aplikacja pozostaje responsywna nawet podczas odczytywania dużych plików lub wykonywania wielu operacji na plikach, ponieważ operacje wejścia-wyjścia są obsługiwane w sposób nieblokujący.

  • tokio::fs::read_to_string
  • tokio::fs::write
  • tokio::fs::File zapewniający większą kontrolę

Asynchroniczne odczytywanie pliku

Oto sposób asynchronicznego odczytywania pliku za pomocą tokio::fs::read_to_string. Aby ten kod zadziałał, należy upewnić się, że w tym samym katalogu co projekt Rust znajduje się plik o nazwie hello.txt (na przykład w src/ lub w katalogu głównym projektu) zawierający dowolną treść.

use tokio::fs;

#[tokio::main]
async fn main() {
  let path = "hello.txt";
  // Create a dummy file for the example if it doesn't exist
  // In a real app, you'd handle file creation/existence more robustly
  if let Err(_) = fs::metadata(path).await {
    fs::write(path, "Hello, Tokio file!").await.unwrap();
  }

  match fs::read_to_string(path).await {
    Ok(content) => println!("File content: '{}'", content),
    Err(e) => eprintln!("Error reading file: {}", e),
  }
}

Asynchroniczne operacje sieciowe

Tokio pokazuje pełnię swoich możliwości w programowaniu sieciowym. Jego moduł tokio::net oferuje nieblokujące mechanizmy komunikacji TCP i UDP.

Ma to kluczowe znaczenie podczas tworzenia wydajnych serwerów lub klientów, które mogą jednocześnie obsługiwać wiele połączeń bez tworzenia osobnego wątku dla każdego z nich.

  • tokio::net::TcpListener dla serwerów.
  • tokio::net::TcpStream dla połączeń klienckich.

Podstawowa struktura asynchronicznego serwera TCP

Choć pełny serwer jest złożony, ten fragment pokazuje główną pętlę asynchronicznego serwera TCP korzystającego z Tokio. Nasłuchuje on przychodzących połączeń i wyświetla komunikat dla każdego z nich. Proszę uruchomić ten kod, a następnie otworzyć w przeglądarce adres http://127.0.0.1:8080, aby zobaczyć połączenia.

use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
  let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
  println!("Listening on: {}", listener.local_addr().unwrap());

  loop {
    let (socket, addr) = listener.accept().await.unwrap();
    println!("Accepted connection from: {}", addr);
    // In a real server, you'd spawn a task to handle the socket
    // tokio::spawn(async move { handle_connection(socket).await; });
  }
}

// fn handle_connection(socket: TcpStream) { /* ... */ } // Placeholder

Wyzwanie: zadania Tokio

Proszę przeanalizować poniższy kod Rust korzystający z Tokio. Jaki będzie *pierwszy* komunikat wyświetlony w konsoli po uruchomieniu programu?

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
  tokio::spawn(async {
    sleep(Duration::from_millis(200)).await;
    println!("Task 1: Done");
  });

  tokio::spawn(async {
    sleep(Duration::from_millis(100)).await;
    println!("Task 2: Done");
  });

  println!("Main: Starting tasks...");

  sleep(Duration::from_millis(300)).await;
  println!("Main: Finishing.");
}

Podsumowanie: tworzenie aplikacji za pomocą Tokio

Wykonali Państwo ważny krok w kierunku tworzenia aplikacji asynchronicznych w Rust i Tokio!

  • Tokio pełni funkcję środowiska uruchomieniowego async, wykonującego kod async.
  • #[tokio::main] jest asynchronicznym punktem wejścia programu.
  • tokio::spawn pozwala równocześnie uruchamiać wiele zadań.
  • tokio::join! pomaga oczekiwać na wiele obiektów typu Future.
  • Tokio zapewnia nieblokujące operacje wejścia-wyjścia dla plików (tokio::fs) i sieci (tokio::net).

Te narzędzia są podstawą tworzenia wysoce współbieżnych i responsywnych aplikacji w Rust. Proszę dalej ćwiczyć!

Bezpłatny start

Ucz się Rust dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
39
Lekcje
144

Często zadawane pytania

Czy lekcja „Tworzenie aplikacji asynchronicznych za pomocą Tokio” jest bezpłatna?

Tak — pełny tekst „Tworzenie aplikacji asynchronicznych za pomocą Tokio” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 3 lekcji w sumie.

Co nauczysz się w „Tworzenie aplikacji asynchronicznych za pomocą Tokio”?

Nauczą się Państwo używać runtime’u Tokio do wydajnego wykonywania zadań asynchronicznych oraz obsługi operacji wejścia-wyjścia i innych operacji współbieżnych. Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?

Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 3.

Ile czasu zajmuje lekcja „Tworzenie aplikacji asynchronicznych za pomocą Tokio”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?

Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wprowadzenie do Async/Await
  2. Tworzenie aplikacji asynchronicznych za pomocą Tokio
  3. Praca z futures i zadaniami
← Powrót do Learn Rust Coding