Socket.IOは、WebSocketをベースとし、自動フォールバックを備えたクライアントとサーバー間の双方向リアルタイム通信のためのライブラリです。チャット、ゲーム、共同編集者における即時データ転送のための信頼性の高いトランスポートを提供します。Socket.IO公式ドキュメント(2024)によると、適切な設定で1台のサーバー上で100万以上の接続を処理します。
重要ポイント
Socket.IOは、クライアントとサーバー間の双方向イベント駆動型通信のためのオープンソースのJavaScriptライブラリです。2010年に開発者のGuillermo Rauchによって作成され、それ以来Node.js上のリアルタイムアプリケーションの事実上の標準となっています。
ネイティブのWebSocket APIとは異なり、Socket.IOはルーム、名前空間、自動再接続、バイナリデータ型などの追加の抽象化を提供します。このライブラリはWebSocketの独立した実装ではなく、トランスポート層としてEngine.IOを使用し、最初にHTTP long-polling接続を確立してからWebSocketへのアップグレードを試みます。
npm統計(2025)によると、socket.ioパッケージは毎週1200万以上ダウンロードされており、Node.jsエコシステムで最も人気のあるライブラリの1つとなっています。Socket.IOは、ブラウザ、iOS、Android、React Native、デスクトップアプリケーションなど、すべての最新プラットフォームでサポートされています。
Socket.IOバージョン1.0は2014年にリリースされ、単一のTCP接続で複数の論理チャネルを多重化できる名前空間の概念を導入しました。バージョン2.0(2017)はバイナリデータのサポートを追加し、パース性能を向上させました。現在のバージョン4.x(2020~2025)は、TypeScriptの完全サポート、スケーリングのための主要なアダプターモード、および改善された後方互換性を含んでいます。
各メジャーリリースはAPIの後方互換性を維持しています。socket.io@2クライアントは特別な互換モードを介してsocket.io@4サーバーに接続できます。これは、クライアント側のアップグレードが段階的に行われる長期プロジェクトにとって重要です。
Socket.IOのアーキテクチャは、サーバーモジュール(npmパッケージsocket.io)とクライアントモジュール(npmパッケージsocket.io-client)の2つのコンポーネントで構成されています。サーバーはNode.js HTTP(S)サーバー上で動作し、トランスポート層を管理するためにEngine.IOを使用します。
最初の接続時、クライアントはサーバーにHTTPリクエストを送信します。Engine.IOが応答し、long-polling接続を確立します。その後、クライアントはトランスポートプロトコルをWebSocketにアップグレードするリクエストを送信します。サーバーがWebSocketをサポートしている場合、アップグレードは単一のTCPセッション内で行われます。そうでない場合、接続はlong-pollingのままで、アプリケーションコードの変更は必要ありません。
Socket.IOパフォーマンステスト(2024)によると、WebSocketを使用した場合のレイテンシはメッセージ送信あたり2〜5msですが、long-pollingはHTTPオーバーヘッドのため150〜300ms追加されます。トランスポートの選択は開発者にとって透過的です。
Engine.IOは、Socket.IOが構築される低レベルのトランスポート層です。接続確立、トランスポート選択、ハートビート(ping/pong)、接続終了を処理します。Engine.IOパケットの主なタイプは、open(初期化)、close(終了)、ping/pong(キープアライブ)、upgrade(トランスポート変更)、message(データ)です。
Socket.IOはEngine.IOの上にイベント駆動モデルを構築します。これが開発者が扱うものです。各Socket.IOメッセージは、配信確認用の一意の識別子を持つEngine.IOパケットにラップされます。
Socket.IOは、ネイティブのWebSocket APIにはなく、リアルタイムアプリケーションの開発を大幅に容易にする一連の機能を提供します。主な機能を見てみましょう。
自動再接続 — 切断時にクライアントは指数バックオフ(100ms、200ms、400ms...最大まで)で自動的に接続を復元します。Socket.IOドキュメント(2024)によると、再試行設定はreconnectionDelayパラメーターとreconnectionAttemptsパラメーターで利用できます。このオプションは、ネットワーク変更中に接続が中断される可能性があるモバイルアプリケーションにとって重要です。
ルームサポート — サーバーはソケットをルームにグループ化し、特定のルームの参加者にのみメッセージを送信できます。ルームは明示的な作成を必要としません。最初のソケットが参加したときに作成されます。ルームはプロセスレベルで実装され、特別なアダプターなしでは異なるサーバー間で共有されません。
名前空間 — 単一の接続上の通信チャネルの論理的な分離。たとえば、チャットメッセージ用の/chat名前空間と通知用の/notifications名前空間。各名前空間には独自のルーム、ミドルウェア、ハンドラーがあります。名前空間は単一のTCP接続で多重化され、リソースを節約します。
配信確認 — メッセージを送信する際に、サーバーが受信を確認したときに呼び出されるコールバック関数を渡すことができます。これは各パケットの一意の識別子を介して実装されます。確認メカニズムにより、重要なメッセージ(支払いトランザクションなど)が受信者に確実に配信されます。
Socket.IOとネイティブWebSocketの選択はプロジェクトの要件によって異なります。WebSocketは標準化されたプロトコル(RFC 6455)であり、すべての最新ブラウザでサポートされています。Socket.IOはWebSocketをトランスポートとして使用するライブラリですが、追加機能を提供します。
| 特性 | Socket.IO | WebSocket |
|---|---|---|
| トランスポート | WebSocket + HTTP long-polling(フォールバック) | WebSocketのみ |
| イベントモデル | JSONペイロード付き名前付きイベント | テキスト/バイナリフレームのみ |
| ルーム | 組み込みソケットグループ化 | 手動実装が必要 |
| 自動再接続 | 組み込み | 手動実装が必要 |
| 配信確認 | コールバック付きACKメカニズム | プロトコル拡張で利用可能 |
| スケーリング | アダプター(Redis、MongoDB、Cluster) | 独自のインフラストラクチャが必要 |
| ライブラリサイズ | 〜50 KB(クライアント、gzip) | ブラウザに組み込み(0 KB) |
プロジェクトで最大限のパフォーマンスと最小限のクライアントサイズが必要な場合は、ネイティブWebSocketを選択してください。信頼性の高い配信、グループ化、イベント駆動モデルが必要な場合は、Socket.IOが既製の抽象化により開発時間を2〜3倍短縮します。
State of JS 2024調査によると、リアルタイムアプリケーション開発者の67%が、便利なAPIとエッジケース(ネットワーク切断、再接続、バイナリデータ)の組み込み処理のためにSocket.IOを好んでいます。
Socket.IOのインストールには、サーバー側とクライアント側の2つのパッケージが必要です。Node.jsプロジェクトの基本的なセットアップを見てみましょう。サーバーはHTTPサーバーを作成し、Socket.IOを初期化し、クライアントの接続および切断イベントを処理します。
Socket.IOドキュメント(2024)によると、サーバーは組み込みのhttpモジュールを使用してExpressなしで起動できますが、実際のプロジェクトでは通常、HTTPリクエストルーティングにExpressまたはFastifyを使用します。
const express = require('express');
const http = require('http');
const Server = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: { origin: '*' }
});
io.on('connection', (socket) => {
console.log('クライアント接続:', socket.id);
socket.emit('welcome', { message: 'Hello from server' });
socket.on('disconnect', () => {
console.log('クライアント切断');
});
});
server.listen(3000, () => {
console.log('サーバーがポート3000で実行中');
});
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000', {
transports: ['websocket', 'polling'],
reconnectionDelay: 1000
});
socket.on('welcome', (data) => {
console.log(data.message);
});
socket.emit('chat message', {
user: 'Alice',
text: 'Hello everyone!'
});
Socket.IOのイベントモデルは名前付きイベントに基づいています。サーバーとクライアントは特定のイベント名にバインドされたメッセージを送受信します。ペイロードは、文字列、JSONオブジェクト、またはバイナリデータ(Buffer、ArrayBuffer、Blob)にすることができます。
各イベントはACK(確認応答)をサポートしています。これは、受信者がイベントを処理した後に送信者側で実行されるコールバック関数を渡すことです。これにより、イベントモデル上にリクエスト-レスポンスパターンを実装できます。ACKは、受信者が明示的にコールバックを呼び出した場合にのみ機能します。
Socket.IOドキュメント(2024)によると、最適なパフォーマンスのために1つのメッセージの最大サイズは1 MBを超えないようにする必要があります。より大きなメッセージはフラグメントに分割するか、別のチャネルを介して送信する必要があります。
io.on('connection', (socket) => {
socket.join('room-1');
socket.to('room-1').emit('user joined', {
userId: socket.id
});
io.to('room-1').emit('message', {
text: 'Broadcast to room'
});
socket.leave('room-1');
});
水平スケーリングでは、複数のサーバープロセス間での状態共有の問題を解決する必要があります。ルーム、名前空間、接続済みソケットのリストは単一のプロセスのメモリに保存され、アダプターなしでは他のプロセスから見えません。
公式のSocket.IOアダプター:redis(Redis Pub/Sub経由)、mongodb(MongoDB change streams経由)、cluster(Node.jsクラスターマルチプロセスモード用)。アダプターはSocket.IOインスタンス間のメッセージブローカーとして機能します。イベントがルームに送信されると、アダプターはそれをRedisに公開し、すべてのサーバーが通知を受け取ります。
Socket.IO負荷テスト(2024)によると、Redisアダプターを備えた4台のサーバーのクラスターは、10ms未満のレイテンシで最大40万の同時接続を処理します。アダプターがない場合、1つのNode.jsプロセスの最大容量は1GBメモリで約10万接続です。
const Server = require('socket.io');
const RedisAdapter = require('@socket.io/redis-adapter');
const Redis = require('ioredis');
const pubClient = new Redis({ host: 'localhost', port: 6379 });
const subClient = pubClient.duplicate();
const io = new Server(server);
io.adapter(RedisAdapter(pubClient, subClient));
KubernetesまたはDocker Swarmを使用する場合、同じクライアントからのリクエストが同じサーバーに届くようにセッションアフィニティ(スティッキーセッション)を追加で設定することをお勧めします。そうしないと、再接続のたびに割り当てが変わる可能性があります。
よくある質問
Socket.IOは、名前付きイベントを使用したイベントモデル、自動再接続、ルームサポート、HTTP long-pollingへのフォールバックを提供します。ネイティブWebSocketは、最小限のAPIを持つ低レベルプロトコルであり、これらのメカニズムの手動実装が必要です。
はい、Python(python-socketio)、Java(netty-socketio)、Go(go-socketio)などの言語向けにサーバー側のサードパーティ実装が存在します。socket.io-clientはJavaScript、Swift、Kotlin、C++で利用可能です。
Socket.IOを使用する単一のNode.jsプロセスは、1GBのRAMで最大10万接続を処理します。Redisアダプターと4台のサーバーを使用すると、クラスターは最大40万の同時クライアントを処理できます。
はい、iOS用の公式Swiftクライアント、Android用のJava/Kotlinクライアントがあります。React Nativeでは、標準のJavaScript socket.io-clientが使用されます。
HTTP/WSの代わりにHTTPS/WSSを使用し、トークン(JWT)による認証用のミドルウェアを設定し、バリデーターを介して送信イベント制限を設定し、DDoS対策にレート制限を使用してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。