Tokioで非同期アプリケーションを構築する
Tokioランタイムを使って非同期タスクを効率的に実行し、I/Oなどの並行処理を扱います。
「Tokioで非同期アプリケーションを構築する」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン2/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。
Tokio ランタイムを見てみる
おかえりなさい!前のレッスンでは、async と await について学びました。しかし、async 関数は実際にはどのように実行されるのでしょうか。
そこで登場するのが、Tokio のような非同期ランタイムです。Tokio は、非同期 Rust コードを実行する環境を提供する強力なライブラリです。
Futureをスケジュールして実行します。- ノンブロッキング I/O 操作を処理します。
- 並行タスクを効率的に管理します。
非同期コードを実行する
Tokio を使い始めるには、通常 #[tokio::main] 属性マクロを使用します。このマクロは async fn main() を、Tokio ランタイムを初期化して非同期コードを実行する標準的な fn main() に変換します。
これは、非同期アプリケーションのエントリーポイントだと考えるとよいでしょう。
use tokio;
#[tokio::main]
async fn main() {
println!("Hello from Tokio!");
}新しい非同期タスクを生成する
Tokio の主要な機能の 1 つは、複数の非同期操作を並行して実行できることです。これには tokio::spawn を使用します。
tokio::spawn は Future を受け取り、Tokio ランタイム上で実行されるようスケジュールします。これにより、生成したタスクがバックグラウンドで実行されている間も、メインタスクは処理を続けられます。
- ノンブロッキングで実行されます。
- 完了を待機するための
JoinHandleを返します。 - タスクは独立して実行されます。
<code>tokio::spawn</code> の動作
tokio::spawn を使ってコードを並行実行する方法を見てみましょう。両方のメッセージが表示されますが、スリープ処理のため、「task complete」より先に「done」が表示される場合があることに注目してください。
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! を使うと、複数の Future を並行して await し、その結果をまとめられます。複数の JoinHandle を `await` する方法に似ていますが、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);
}Tokio で非同期ファイル I/O
従来のファイル操作はスレッドをブロックする可能性があり、非同期アプリケーションには適していません。Tokio の tokio::fs モジュールは、ファイルシステム操作の非同期版を提供します。
これにより、I/O がノンブロッキングで処理されるため、大きなファイルを読み込んだり、多数のファイル操作を行ったりしている間も、アプリケーションの応答性を保てます。
tokio::fs::read_to_stringtokio::fs::write- より細かく制御するための
tokio::fs::File
ファイルを非同期で読み込む
tokio::fs::read_to_string を使ってファイルを非同期で読み込む方法を見てみましょう。このコードを実行するには、Rust プロジェクトと同じディレクトリ(例:src/ 内またはプロジェクトのルート)に、内容を含む hello.txt という名前のファイルがあることを確認してください。
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 サーバーの基本構造
完全なサーバーは複雑ですが、このコード例では Tokio を使った非同期 TCP サーバーの中心的なループを示しています。受信接続を待ち受け、接続ごとにメッセージを表示します。実行したら、ブラウザーで 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) { /* ... */ } // PlaceholderTokio タスクチャレンジ
Tokio を使った次の Rust コードについて考えてみましょう。このプログラムを実行したとき、コンソールに最初に表示されるメッセージは何でしょうか。
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!は、複数の Future の await に役立ちます。- Tokio は、ファイル(
tokio::fs)とネットワーク(tokio::net)向けにノンブロッキング I/O を提供します。
これらのツールは、Rust で高い並行性と応答性を備えたアプリケーションを作成するための基本要素です。練習を続けてください。
よくある質問
「Tokioで非同期アプリケーションを構築する」レッスンは無料ですか?
はい。「Tokioで非同期アプリケーションを構築する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。
「Tokioで非同期アプリケーションを構築する」で何を学びますか?
Tokioランタイムを使って非同期タスクを効率的に実行し、I/Oなどの並行処理を扱います。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/3です。
「Tokioで非同期アプリケーションを構築する」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Async/Await入門
- Tokioで非同期アプリケーションを構築する
- Futureとタスクを扱う