top of page

Rustで始めるリアルタイムチャットサーバー構築:実装手順を詳しく解説

Rustで始めるリアルタイムチャットサーバー構築:実装手順を詳しく解説

リアルタイムチャットの仕組みをゼロから作ってみたい!そんなエンジニア向けに、この記事では Rust と WebSocket を活用して、複数クライアントが同じルーム内でメッセージをやり取りできる簡易的なチャットサーバーを構築する手順を紹介します。


Rustの非同期処理フレームワークである axum と tokio-tungstenite を使いながら、基本的な接続の実装からルーム管理、メッセージのブロードキャストまでをわかりやすく解説。Rust初心者でも安心して取り組める内容ですので、一緒にリアルタイム通信の世界を楽しんでみましょう!




本記事のゴール

axum と tokio-tungstenite を用いて、複数クライアントが同一のルームでメッセージを送り合う、簡易的なリアルタイムチャットサーバーを作成します。


前提知識と準備

  • WebSocket の基本概念を理解していること

  • Rust と Cargo がインストール済みであること

実装の流れ

1. プロジェクト作成と依存関係設定

まずはプロジェクトを作成。



Cargo.toml に必要な依存を追加します。




2. WebSocket 接続を受け付ける基本構造

最初は、WebSocket 接続を受け付けて、クライアントとやり取りする最小の構造を作ります。

この段階では、まだルームの概念やブロードキャストはありません。

ただ接続してメッセージを受け取り、そのまま送り返すだけの機能を実装します。

axum::extract::ConnectInfo は、接続情報を取得するための Extractor です。

使わなくても動作に影響はありませんが、接続元の IP アドレスなどを取得する際に便利です。




動作確認

1. サーバー起動


2. wscat で接続



3. テキストメッセージを送信



そのまま返ってくれば OK。

3. ルームとクライアント管理の仕組み

特定のルームに参加した複数クライアント間でメッセージを共有したい場合、接続状態をサーバー側で保持する必要があります。

今回は簡略化のため、データベースやキャッシュストア、PubSub システムなどを使わず、サーバーのメモリ上で管理します。

ここでは、以下の構造体を導入して、状態を管理します。

  • Room

    • 文字列で識別されるチャット部屋

  • Peer

    • クライアントを識別する要素(SocketAddr で識別)

    • ユーザーの認証情報などを使用してクライアントを識別したほうがいいと思うけど、IP アドレスで代用しちゃう

  • PeerKey

    • (Room, Peer) のペア

    • 特定のルームに所属するクライアントを識別するためのキー

  • AppState

    • サーバーの状態を保持する構造体

    • Arc<Mutex<HashMap<PeerKey, Peer>>> で、ルームとクライアントの紐づけを管理

    • DashMap などの並行処理に強い HashMap を使ったほうがいいと思うけど、Arc<Mutex<>> で代用しちゃう



AppState を main() で初期化し、Router に組み込みます。




4. メッセージの種類とルーム参加・退出

クライアントから

  • ルームに参加

  • ルームから退出

  • メッセージ配信

を表すペイロードを受け取り、イベントごとに処理を分岐させます。



この列挙型を使って、{"event":"join","room":"general"} のような JSON をパースして、ユーザーのリクエストを判別します。

5. WebSocket ハンドラでの参加・退出・ブロードキャスト処理

ここまでで、

  • WebSocket 接続を受け付ける基本構造

  • ルームとクライアント管理の仕組み

  • メッセージの種類とルーム参加・退出

が整いました。

次は、実際のハンドラ handle_socket 関数内で、参加・退出・メッセージ配信の機能を実装します。

ポイントは以下の通りです。

1. 受信タスク (recv_task) と送信タスク (send_task) の分離

  • 受信処理と送信処理を独立した並行タスクとして管理し、コードの見通しを良くしておく

    • recv_task

      • クライアントからのメッセージを受け取り、イベント内容に応じてルームへの追加・削除・メッセージ配信を行うタスク

    • send_task

      • サーバーからクライアントへのメッセージ送信を行うタスク

全体像


recv_task(受信タスク)


send_task(送信タスク)


タスクの終了待ち合わせ




2. ルーム参加 (join) 処理

  • クライアントが {"event":"join","room":"general"} のようなイベントを送信した場合、そのクライアントを AppState の rooms に登録する

  • このクライアントにメッセージをブロードキャストできるよう、Room と SocketAddr の複合キーに紐づけておく



3. ルーム退出 (leave) 処理

  • クライアントが {"event":"leave","room":"general"} のようなイベントを送信した場合、そのクライアントを該当ルームから削除する

  • クライアントが明示的に leave を送らず、ソケットが切断された場合でも、後片付けとして参加中の全ルームからクライアントを削除しておく


4. メッセージ配信 (broadcast) 処理

  • クライアントが {"event":"broadcast","room":"general","message":"Hello"} のようなイベントを送信した場合、該当ルームに参加している全てのクライアントへ "Hello" のメッセージを送信する



これで、基本的な「参加・退出・メッセージ配信」のサイクルが完成しました。

ちゃんと動くか確認してみましょう。

動作確認

1. サーバー起動


2. wscat で接続

3. ルームに参加

コンソールに 127.0.0.1:XXXXX joined room general と表示されれば OK。

4. もう 1 つのコンソールで同じ手順を繰り返し、同じルームに参加


5. ルームにメッセージを配信


2 つのコンソールに Hello! と表示されれば OK。

6. ルームから退出



再度メッセージを配信しても、退出したクライアントのコンソールに届かなければ OK。



GOOD 👍️


まとめ


本記事では、Rust でリアルタイムチャットサーバーを実装する手順を紹介しました。

今回紹介したのは、あくまでも「最低限の仕組み」ですが、Rust を用いたマルチスレッドや非同期処理の概要を掴むには役立ったかなと感じています。

実運用を考えると、モニタリングやスケーリング、セキュリティなど、さまざまな課題が待ち受けています。

でもまぁ、Rust は書いてて楽しいので頑張れそうですw

もし、この記事が Rust でのリアルタイム通信の基本構造を理解する一助になれば幸いです。


ありがとうございました!


Black and White Silhouette Motivational Quotes Facebook Cover (1).png

運営会社

人気記事

​最新記事

インフラ構築 (2) (1).png
インフラソリューション.png

運営会社

drecom_image.jpg
会社概要

名称:株式会社ドリコム(3793:東証グロース)
代表:代表取締役社長 内藤裕紀
設立:2001年11月13日
社員数:369名(2024年3月31日現在)
所在地:東京都品川区大崎 2丁目1番1号
   
    ThinkPark Tower 19 階
URL:https://drecom.co.jp/

事業内容
・ゲーム開発/運営(スマートフォン、PC)
・出版、映像制作
・物販、イベント運営
・ビジネスソリューション
・ARサービス開発
・Web3(ブロックチェーン)サービス開発
・生成AIサービス開発

with entertainment ~人々の期待を超える~

ドリコムが常に目指しているのは、新しい体験やサービスを産み出し、人をワクワクさせること。
ドリコムのサービスで世の中をワクワクさせ、毎日をもっとハッピーにしたい。そういう会社でありたいという思いが込められています。

Copyright (C)「ITインフラの課題解決をアウトソーシングするための情報提供サイト」 All Rights Reserved.

bottom of page