0Pricing
Learn Rust Coding · Урок

Создание асинхронных приложений с Tokio

Используйте среду выполнения Tokio для эффективного выполнения асинхронных задач, обработки ввода-вывода и других параллельных операций.

«Создание асинхронных приложений с Tokio» — бесплатный урок Learn Rust Coding на CoddyKit. Это урок 2 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Learn Rust Coding, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Learn Rust Coding содержит 3 уроков всего.

Знакомство со средой выполнения Tokio

С возвращением! На предыдущем уроке Вы узнали об async и await. Но как именно выполняется функция async?

Здесь в игру вступает асинхронная среда выполнения, такая как Tokio. Tokio — мощная библиотека, предоставляющая среду выполнения для Вашего асинхронного кода на Rust.

  • Планирует и выполняет объекты типа Future.
  • Обрабатывает неблокирующие операции ввода-вывода.
  • Эффективно управляет параллельными задачами.

Выполнение асинхронного кода

Чтобы начать работать с Tokio, обычно используют макрос атрибута #[tokio::main]. Этот макрос преобразует Вашу async fn main() в обычную fn main(), которая инициализирует среду выполнения Tokio и запускает Ваш асинхронный код.

Представляйте его как точку входа в асинхронное приложение.

use tokio;

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

Запуск новых асинхронных задач

Одна из ключевых возможностей Tokio — запуск нескольких асинхронных операций одновременно. Для этого можно использовать tokio::spawn.

tokio::spawn принимает Future и планирует его выполнение в среде Tokio. Благодаря этому основная задача может продолжать выполняться, пока запущенная задача работает в фоновом режиме.

  • Он не блокирует выполнение.
  • Возвращает JoinHandle, с помощью которого можно дождаться завершения.
  • Задачи выполняются независимо.

<code>tokio::spawn</code> в действии

Посмотрим, как tokio::spawn позволяет выполнять код одновременно. Обратите внимание: оба сообщения появляются, но сообщение «done» может быть выведено раньше сообщения «task complete» из-за задержки.

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.");
}

Ожидание нескольких задач

Когда у Вас есть несколько задач, часто требуется дождаться завершения всех. Для этого Tokio предоставляет макрос tokio::join!.

tokio::join! позволяет одновременно дождаться нескольких фьючерсов и объединить их результаты. Он похож на ожидание нескольких JoinHandle с помощью `await`, но обычно короче для фиксированного набора фьючерсов.

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);
}

Асинхронный файловый ввод-вывод с Tokio

Традиционные операции с файлами могут блокировать поток, что плохо для асинхронных приложений. Модуль tokio::fs предоставляет асинхронные версии операций с файловой системой.

Благодаря этому приложение остаётся отзывчивым даже при чтении больших файлов или выполнении множества операций с файлами, поскольку ввод-вывод обрабатывается неблокирующим образом.

  • tokio::fs::read_to_string
  • tokio::fs::write
  • tokio::fs::File для более гибкого управления

Асинхронное чтение файла

Вот как можно асинхронно прочитать файл с помощью tokio::fs::read_to_string. Чтобы этот код выполнился, убедитесь, что в том же каталоге, что и проект Rust, находится файл с именем hello.txt (например, внутри src/ или в корневом каталоге проекта) и что в нём есть содержимое.

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),
  }
}

Асинхронные сетевые операции

Tokio особенно хорошо проявляет себя в сетевом программировании. Его модуль tokio::net предлагает неблокирующие примитивы для взаимодействия по TCP и UDP.

Это крайне важно для создания высокопроизводительных серверов или клиентов, способных одновременно обрабатывать множество подключений без выделения отдельного потока для каждого из них.

  • tokio::net::TcpListener для серверов.
  • tokio::net::TcpStream для клиентских подключений.

Базовая структура асинхронного TCP-сервера

Хотя полноценный сервер довольно сложен, этот фрагмент показывает основной цикл асинхронного TCP-сервера на Tokio. Он ожидает входящие подключения и выводит сообщение для каждого из них. Попробуйте запустить код, а затем откройте в браузере http://127.0.0.1:8080, чтобы увидеть подключения.

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

Задача на задачи Tokio

Рассмотрите следующий код на Rust с использованием Tokio. Какое *первое* сообщение будет выведено в консоль при запуске этой программы?

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.");
}

Итоги: разработка с Tokio

Вы сделали важный шаг к созданию асинхронных приложений на Rust и Tokio!

  • Tokio выступает в роли асинхронной среды выполнения, исполняющей Ваш код async.
  • #[tokio::main] — асинхронная точка входа в Вашу программу.
  • tokio::spawn позволяет одновременно выполнять несколько задач.
  • tokio::join! помогает дождаться нескольких фьючерсов.
  • Tokio предоставляет неблокирующий ввод-вывод для файлов (tokio::fs) и сетей (tokio::net).

Эти инструменты необходимы для создания высококонкурентных и отзывчивых приложений на Rust. Продолжайте практиковаться!

Часто задаваемые вопросы

Урок «Создание асинхронных приложений с Tokio» бесплатный?

Да — полный текст урока «Создание асинхронных приложений с Tokio» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Learn Rust Coding, подпишись на CoddyKit PRO. Курс Learn Rust Coding содержит 3 уроков всего.

Чему я научусь в уроке «Создание асинхронных приложений с Tokio»?

Используйте среду выполнения Tokio для эффективного выполнения асинхронных задач, обработки ввода-вывода и других параллельных операций. Ты практикуешь Learn Rust Coding с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Learn Rust Coding?

Предыдущий опыт не требуется. Learn Rust Coding на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 3.

Сколько времени занимает урок «Создание асинхронных приложений с Tokio»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Learn Rust Coding?

Да. Каждый урок Learn Rust Coding включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Введение в Async/Await
  2. Создание асинхронных приложений с Tokio
  3. Работа с будущими и задачами
← Назад к Learn Rust Coding