WebSocketを扱うことができるNode.jsのライブラリです。
WebSocketを直接扱うのとの違い
WebSocketを単体で扱っても実装は可能です。Socket.IOを使うメリットは以下です。
他の通信をサポートしている。
WebSocketがサポートされていない環境でもポーリングや、JSONPなどの他の通信機能を用いて通信ができるので幅広い環境で活用できます。
接続されている全てのクライアントにブロードキャストできる
プレーンなWebSocketの場合は、接続されているクライアントのリストを見て一回一回送信する必要があります。
自動的に再接続してくれる
プレーンなWebSocketの場合は、自動的に再接続はしてくれません。再接続の処理を記述する必要があります。
リリースノート
1.0.0
2014年5月にリリースされた。旧バージョン(1.0.0以前)のAPIが廃止されたので互換性がない。
できること
チャットなどの送受信されるメッセージ内容が即時反映されるリアルタイムWebアプリケーションを実装することが可能です。
制約
誰かが書き込んだら、リアルタイムで他のユーザーにも反映されます。Socket.IOサーバーが全てのクライアントに通知してくれる仕組みです。ただし、全ての利用ユーザーがオンラインである必要があります。
P2Pではダメなのか?
いちいち、Socket.IOサーバーが必要になるので、サーバーのいらないP2P接続じゃダメなの?と思われるかもしれませんが、それだとNATやFirewallを超えるSTUNサーバーなどを用意する必要があり結局サーバーが必要になってしまうのでどっちもどっちになるためです。
大まかな仕組み
何か、イベントが発生した時に動く「イベント駆動」になっています。
チャットで呟いた人が、postイベントを送信すると、他の全クライアントに対して「member-post」というイベントを別途発行します。
room、namespace
Socket.ioはデータ送受信だけでなく、roomやnamespaceなどのライブラリも提供しています。
room
双方向・リアルタイムデータ送受信を任意の範囲で行うための仕組み。文字通り、その部屋に所属するクライアント間のみでデータをやりとりすることが可能
namespace
Socket.IOの実装を機能単位で分割するための仕組み。チャットアプリに外部API連携機能や、お知らせ機能などを実装したい場合はこれを使って実装するとよい。
実装
socket.ioを使う場合は、フロントエンドとバックエンドでそれぞれやりとりを行うのでそれぞれの書き方を把握する必要があります。
初期化
フロントエンド
以下の例で言えば、ルートパスとコネクトします。socket.ioではioオブジェクトを使用して通信経路を開きます。
1 |
const socket = io("http://サーバーのIP:ポート番号"); |
通常のwebsocket APIと異なりsocket.ioはWebSocket以外のプロトコルにも対応しているのでwsではなく、httpになっています。
バックエンド
Node.js環境でフレームワークにExpressを使う場合は下記のように記述します。どのサーバーでソケット通信をするかsocket.ioに伝えます。
1 2 3 4 |
const express = require("express"); const app = express(); const server = require("http").Server(app); const io = require("socket.io")(server); |
イベント送信
フロントエンド
1 |
socket.emit("イベント名", 送信パラメータ1,送信パラメータ2); |
バックエンド
同じルーム内の全てのユーザーに送信できます。(ブロードキャスト)
1 |
socket.broadcast.emit("イベント名", 送信パラメータ); |
イベント受信
これも基本バックエンドも、フロントエンドも同じ書き方です。
第二引数でコールバック関数を指定します。
1 2 3 |
socket.on("イベント名", (受信パラメータ) => { やりたいこと。 }); |
バックエンドの場合
一旦、サーバーでつかまえてからsocketのイベントハンドラの登録をします。
1 2 3 |
io.on("connection", (socket) => { socket.on("xxx",()=>{}) } |
バックエンドのみ:ルームに新規ユーザーを追加
ルームに新規ユーザーを追加します。
1 |
socket.join(roomId); |
フロントエンドのみ:ソケット通信を切断する。
1 |
socket.disconnect(); |
sticky-sessionとは?
socket.ioのサーバーをclusterモジュールを使ってスケールアウトしようとした際に、コネクション確立時に別のプロセス(サーバー)が割り振られてしまうのでエラーになる。これを解決する仕組みです。
仕組み
内部でclusterが使われていてsticky.listenというAPIを呼べば複数のプロセスを自動でforkしてくれます。デフォルトで使っているサーバーのCPUの数だけforkします。
実装例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const cluster = require("cluster"); const io = require("socket.io")(); const sticky = require("sticky-session"); const http = require("http"); const server = http.createServer((req, res) => { res.end("worker: " + cluster.worker.id); }); io.attach(server); isWorker = sticky.listen(server, 3000); console.log(isWorker); if (isWorker) { io.on("connection", (socket) => { console.log(`worker: ${cluster.worker.id}, connected, id: ${socket.id}`); // socket.ioの処理 }); } |
この記事へのコメントはありません。