前回、WebSocketとSocket.IOの違いについて整理しました。
簡単にまとめると、
WebSocket=双方向通信を行うための標準的な仕組み
Socket.IO=WebSocketなどを利用して
リアルタイムアプリを作りやすくするライブラリ
という違いでした。
そこで次に気になったのが、
「Socket.IOってNode.js専用なの?」
ということ。
Socket.IOというと、
const { Server } = require("socket.io");
のようなNode.jsのコードをよく見るので、なんとなくJavaScript専用の技術のようなイメージがあります。
しかし、実際にはそうではありません。
今回はSocket.IOの対応言語と、勉強中のPythonのFastAPIから使う場合について整理しておきます。
Socket.IOはNode.js専用ではない
Socket.IO公式ドキュメントには、複数言語のサーバー実装とクライアント実装が掲載されています。
まずサーバー側。
主なものとして、
| 言語 | Socket.IOサーバー実装 |
|---|---|
| JavaScript / Node.js | ○ |
| JavaScript / Deno | ○ |
| Java | ○ |
| Python | ○ |
| Go | ○ |
| Rust | ○ |
などがあります。
一番よく見るのは、
ブラウザ
↓
Socket.IO Client
↓
Node.js
↓
Socket.IO Server
という構成だと思います。
Node.jsとの組み合わせが非常に一般的なのでSocket.IO=Node.jsという印象がありますが、PythonなどでもSocket.IOサーバーを実装できます。
クライアント側はさらに多い
Socket.IO公式ドキュメントには、クライアント実装として、
JavaScript
Java
C++
Swift
Dart
Python
.NET
Rust
Kotlin
PHP
Go
などが掲載されています。
そのため、
Webブラウザ
JavaScript
│
│
Android
Java / Kotlin
│
│
iPhone
Swift
│
│
Flutter
Dart
│
↓
Socket.IO
↓
Socket.IO Server
という構成も可能です。
つまり、
Socket.IOはJavaScript同士でしか通信できない仕組みではありません。
両側にSocket.IOプロトコルを扱える実装があれば、異なる言語同士でも通信できます。
WebSocketの場合は?
ここでWebSocketとの違いがまた出てきます。
WebSocketは特定のプログラミング言語用ライブラリではありません。
通信プロトコルです。
そのため、
JavaScript
Python
Java
C#
Go
Rust
C++
など
さまざまな言語からWebSocketを利用できます。
例えば、
ブラウザ
JavaScript
│
│ WebSocket
↓
Python
FastAPI
という通信もできます。
WebSocketという共通の通信プロトコルを双方が理解しているからです。
Socket.IOの場合は双方がSocket.IOを理解する必要がある
Socket.IOの場合は少し違います。
例えば、
JavaScript
Socket.IO Client
↓
Python
Socket.IO Server
なら通信できます。
しかし、
普通のWebSocket Client
↓
Socket.IO Server
では通信できません。
Socket.IOでは、WebSocketの上にSocket.IOやEngine.IO独自の情報が追加されるためです。
つまり、
言語が同じかどうか
より、
同じプロトコルを理解できるか
のほうが重要です。
Pythonの場合はpython-socketio
Pythonには、
python-socketio
というSocket.IO実装があります。
これを使えばPythonでSocket.IOのサーバーやクライアントを作ることができます。
例えば、
import socketio
# 非同期Socket.IOサーバーを作成
sio = socketio.AsyncServer(
async_mode="asgi"
)
といった形です。
そして、
@sio.event
async def connect(sid, environ):
# クライアントが接続したとき
print("接続:", sid)
@sio.event
async def message(sid, data):
# messageイベントを受信
print("受信:", data)
のように、Node.js版Socket.IOと似たイベントベースのプログラムを書くことができます。
ではFastAPIは?
PythonでWeb APIを作るならFastAPIを使うことも多いです。
では、
FastAPIでリアルタイム通信をしたい場合はSocket.IOが必要なのか?
というと、必要ではありません。
FastAPIはWebSocketを利用できます。
整理すると、
FastAPI
├─ WebSocket
│ └─ そのまま利用可能
│
└─ Socket.IO
└─ python-socketioなどを組み合わせる
という関係です。
FastAPI + WebSocket
FastAPIでWebSocketを利用する場合は、例えば次のように書けます。
from fastapi import FastAPI, WebSocket
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
# WebSocket接続を許可
await websocket.accept()
while True:
# クライアントからメッセージを受信
data = await websocket.receive_text()
# クライアントへメッセージを返信
await websocket.send_text(
f"受信しました: {data}"
)
ブラウザ側は普通のWebSocket APIです。
// FastAPIのWebSocketへ接続
const socket = new WebSocket(
"ws://localhost:8000/ws"
);
// 接続完了
socket.addEventListener("open", () => {
// サーバーへ送信
socket.send("こんにちは");
});
// メッセージ受信
socket.addEventListener("message", (event) => {
console.log(event.data);
});
構成としては、
ブラウザ
JavaScript WebSocket API
↓
WebSocket
↓
FastAPI
非常にシンプルです。
FastAPI + Socket.IO
一方、
Roomを使いたい
Socket.IOのイベント通信を使いたい
ACKを使いたい
Socket.IOクライアントと通信したい
といった場合には、PythonのSocket.IO実装を組み合わせる方法があります。
例えば、
import socketio
from fastapi import FastAPI
# FastAPIアプリ
fastapi_app = FastAPI()
# Socket.IOサーバー
sio = socketio.AsyncServer(
async_mode="asgi"
)
@sio.event
async def connect(sid, environ):
# クライアント接続
print("接続:", sid)
@sio.event
async def message(sid, data):
# メッセージ受信
print("受信:", data)
# クライアントへイベント送信
await sio.emit(
"message",
f"受信しました: {data}",
to=sid
)
# FastAPIとSocket.IOをASGIアプリとしてまとめる
app = socketio.ASGIApp(
sio,
fastapi_app
)
ブラウザ側は通常のWebSocket APIではなくSocket.IO Clientを使います。
// Socket.IOサーバーへ接続
const socket = io("http://localhost:8000");
// messageイベントを受信
socket.on("message", (data) => {
console.log(data);
});
// messageイベントを送信
socket.emit("message", "こんにちは");
つまり、
FastAPI + WebSocket
と、
FastAPI + Socket.IO
は同じものではありません。
FastAPIならどっちを使えばいい?
これは用途次第です。
例えば、
サーバーからブラウザへ通知する
リアルタイムログを表示する
処理状況を通知する
シンプルなチャットを作る
程度なら、
FastAPI
+
WebSocket
から検討すれば十分です。
WebSocketという標準的な仕組みをそのまま使えるため、構成もシンプルです。
一方、
Roomを多数使う
イベント名を使って通信したい
自動再接続が欲しい
ACKが欲しい
ブロードキャストを簡単に扱いたい
すでにSocket.IOクライアントを使用している
のであれば、
FastAPI
+
python-socketio
という構成も候補になります。
Node.jsとFastAPIで整理すると
ここまでをまとめると、
Node.js
├─ WebSocket
└─ Socket.IO
Python / FastAPI
├─ WebSocket
└─ python-socketio + FastAPI
となります。
つまり、
Socket.IOを使うためにNode.jsを選ばなければならないわけではない
ということです。
Pythonでも利用できます。
ただし、FastAPIにはもともとWebSocketを扱う仕組みがあるので、
リアルタイム通信をしたい=Socket.IO
と考える必要もありません。
まず、
WebSocketだけで十分なのか?
を考えて、
必要ならSocket.IOを選択する。
これが分かりやすそうです。
最後に
今回の内容を一枚にするとこんな感じ。
リアルタイム通信
│
┌───────────┴───────────┐
↓ ↓
WebSocket Socket.IO
│ │
標準プロトコル 独自プロトコル
│ │
多くの言語で利用 対応ライブラリが必要
│ │
┌────┴────┐ ┌──────┴──────┐
↓ ↓ ↓ ↓
Node.js FastAPI Node.js Python
python-socketio
覚えておきたいのは、
WebSocketもSocket.IOもNode.js専用ではない。
そしてFastAPIなら、
WebSocket
を直接使うこともできるし、
python-socketio
を組み合わせてSocket.IOを利用することもできます。
リアルタイム通信だからとりあえずSocket.IO、ではなく、
必要な機能を見てWebSocketとSocket.IOを選ぶ
ということですね。
これもまた忘れそうなのでメモ。
あ、自分も完全に理解したわけじゃないので技術的な質問はしないでください。(笑)

0 件のコメント:
コメントを投稿