はじめに
チャットアプリやオンラインゲームなどの リアルタイム通信 では、WebSocket というプロトコルが使われることが多いです。
WebSocket の仕組みをざっくり整理して、リアルタイム対戦三目並べを例に実装の雰囲気をつかんでみます 🎮
1. WebSocket とは
WebSocket とは、クライアントとサーバー間で双方向通信を可能にするプロトコル です。
HTTP と同じく、アプリケーション層のプロトコル です。
1.1 HTTP との違い
WebSocket は HTTP と次のような違いがあります。
| HTTP | WebSocket | |
|---|---|---|
| 接続 | 送信ごとに接続・切断 | 一度接続すれば維持される |
| 通信方向 | 基本は一方通行(クライアント → サーバー) | 双方向(クライアント ↔ サーバー) |
| 用途 | 普通の Web ページなど | チャット、リアルタイムゲームなど |
1.2 通信の仕組み
WebSocket 接続は、TCP 接続を確立した上で HTTP Upgrade リクエスト を送ると開始されます。
接続終了するときは、WebSocket Close Frame を送りあった後、TCP 接続も終了します。
1. TCP 接続を確立する
まずは通常の TCP のやり取りから始まります。
クライアントとサーバーの 3 ウェイ・ハンドシェイク によって TCP 接続が成立します 🤝(ここまでは通常の HTTP と同じ)
2. HTTP Upgrade リクエストを送信する
TCP 接続が確立したら、クライアントは「WebSocket に切り替えたい(Upgrade リクエスト)」と HTTP でリクエストします。
GET /notifications HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
3. サーバーが承認する
サーバーが承認すると、「OK!(101 Switching Protocols)」 とレスポンスが返ってきます 🙆♂️
ここで HTTP 通信が WebSocket 通信に切り替わります。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
4. WebSocket で双方向通信を行う
接続が切り替わった後は、クライアント・サーバー間で WebSocket フレーム を使ってリアルタイムに双方向通信ができます。
5. 接続を終了する
通信を終えるときは、まず WebSocket Close フレーム をお互いに送り合います。
その後、TCP レベルでも 4 ウェイ・ハンドシェイク を行い、完全に接続が終了します 👋
2. 実装例: リアルタイム対戦三目並べ
実装の詳細はリポジトリを見てください 💁♂️
2.1 ディレクトリ構成
tic-tac-toe-ws/
├── client/
├── common/
└── server/
各ディレクトリの要点はこんな感じです 👇
2.1.1 共通の型定義: common/
サーバーとクライアントで共通して使う型をまとめて定義しています。
型安全に両者で同じルール・データ構造を共有します。
-
types.ts: ゲームの状態やメッセージの型定義-
Player,Winner,Boardなどの型 - クライアント ⇔ サーバーの通信メッセージ型 (
AssignMessage,MoveMessage,UpdateMessage,ResetMessage)
-
- index.ts: 型定義をまとめてエクスポート
2.1.2 サーバーアプリ: server/
WebSocket サーバーです。
ゲームのロジックを管理し、クライアントに状態を通知します。
-
server.ts: サーバー本体- 接続中のクライアント管理 (
playerAssignments) - ゲーム状態管理 (
board,next,checkWinner()) - メッセージ処理
-
move: 手を打つ -
reset: ゲームリセット
-
- 全クライアントへのブロードキャスト
- 接続中のクライアント管理 (
2.1.3 クライアントアプリ: client/
React アプリです。
サーバーから受け取った状態を表示し、ユーザーの操作をサーバーに送信します。
-
src/App.tsx: React アプリ- WebSocket 接続の管理
- サーバーからのメッセージ受信 (
assign,update) による状態更新 - ユーザーの操作 (
sendMove,sendReset) の送信 - 盤面レンダリングと UI 表示
2.2 処理の流れ(シーケンス図)
処理の流れをおえかきしてみました 🧑🎨(観戦者は割愛)
各クライアントとサーバーがそれぞれ接続を維持して、双方向に通信していることがわかります 🧶
client/ を Vercel、server/ を Render などにデプロイすればお友達と遊べます 🐘(動作確認済みです)
おわりに
「Web を支える技術」って本で HTTP の仕組みが詳しく説明されていて、その中のステータスコードについての説明の部分で「101 は Switching Protocols を表してて HTTP/1.1 からプロトコルをアップグレードする時に使うけど、現時点だとぶっちゃけ使いどころ無い」みたいに書かれててとても悲しい気持ちになってたけど、WebSocket が登場した事によってちゃんと使いどころが見つかったみたいで良かった。(『WebSocket について調べてみた。』より)
私も『Web を支える技術』を読んだとき「使い道ないんだ~」と思った記憶があるのでかなり感動しました。
参考