サーバーインスタンス
サーバーインスタンス(コード例ではしばしばio
と呼ばれます)には、アプリケーションで役立つ可能性のあるいくつかの属性があります。
また、メイン名前空間のすべてのメソッドを継承しています。例えば、namespace.use()
(こちらを参照)やnamespace.allSockets()
などです。
Server#engine
基盤となるEngine.IOサーバーへの参照。
これを使用して、現在接続されているクライアントの数を取得できます。
const count = io.engine.clientsCount;
// may or may not be similar to the count of Socket instances in the main namespace, depending on your usage
const count2 = io.of("/").sockets.size;
または、カスタムセッションID(sid
クエリパラメータ)を生成できます。
const uuid = require("uuid");
io.engine.generateId = (req) => {
return uuid.v4(); // must be unique across all Socket.IO servers
}
socket.io@4.1.0
の時点で、Engine.IOサーバーは3つの特別なイベントを発行します。
initial_headers
: セッションの最初のHTTPリクエスト(ハンドシェイク)のレスポンスヘッダーを書き込む直前に発行され、それらをカスタマイズできます。
io.engine.on("initial_headers", (headers, req) => {
headers["test"] = "123";
headers["set-cookie"] = "mycookie=456";
});
headers
: セッションの各HTTPリクエスト(WebSocketアップグレードを含む)のレスポンスヘッダーを書き込む直前に発行され、それらをカスタマイズできます。
io.engine.on("headers", (headers, req) => {
headers["test"] = "789";
});
connection_error
: 接続が異常終了した場合に発行されます。
io.engine.on("connection_error", (err) => {
console.log(err.req); // the request object
console.log(err.code); // the error code, for example 1
console.log(err.message); // the error message, for example "Session ID unknown"
console.log(err.context); // some additional error context
});
考えられるエラーコードの一覧は次のとおりです。
コード | メッセージ |
---|---|
0 | "Transport unknown" |
1 | "Session ID unknown" |
2 | "Bad handshake method" |
3 | "Bad request" |
4 | "Forbidden" |
5 | "Unsupported protocol version" |
ユーティリティメソッド
Socket.IO v4.0.0では、Socketインスタンスとそのルームを管理するためのいくつかのユーティリティメソッドが追加されました。
socketsJoin
: 一致するソケットインスタンスを、指定されたルームに参加させます。socketsLeave
: 一致するソケットインスタンスを、指定されたルームから離脱させます。disconnectSockets
: 一致するソケットインスタンスを切断させます。fetchSockets
: 一致するソケットインスタンスを返します。
serverSideEmit
メソッドは、Socket.IO v4.1.0で追加されました。
これらのメソッドはブロードキャストと同じセマンティクスを共有し、同じフィルターが適用されます。
io.of("/admin").in("room1").except("room2").local.disconnectSockets();
これは、"admin"名前空間のすべてのSocketインスタンスを作成します。
- "room1"ルーム内(
in("room1")
またはto("room1")
) - "room2"内のものを除く(
except("room2")
) - そして、現在のSocket.IOサーバーのみで(
local
)
切断します。
また、これらはRedisアダプター(socket.io-redis@6.1.0
以降)とも互換性があり、Socket.IOサーバー間で動作することを意味することに注意してください。
socketsJoin
このメソッドは、一致するSocketインスタンスを指定されたルームに参加させます。
// make all Socket instances join the "room1" room
io.socketsJoin("room1");
// make all Socket instances in the "room1" room join the "room2" and "room3" rooms
io.in("room1").socketsJoin(["room2", "room3"]);
// make all Socket instances in the "room1" room of the "admin" namespace join the "room2" room
io.of("/admin").in("room1").socketsJoin("room2");
// this also works with a single socket ID
io.in(theSocketId).socketsJoin("room1");
socketsLeave
このメソッドは、一致するSocketインスタンスを指定されたルームから離脱させます。
// make all Socket instances leave the "room1" room
io.socketsLeave("room1");
// make all Socket instances in the "room1" room leave the "room2" and "room3" rooms
io.in("room1").socketsLeave(["room2", "room3"]);
// make all Socket instances in the "room1" room of the "admin" namespace leave the "room2" room
io.of("/admin").in("room1").socketsLeave("room2");
// this also works with a single socket ID
io.in(theSocketId).socketsLeave("room1");
disconnectSockets
このメソッドは、一致するSocketインスタンスを切断させます。
// make all Socket instances disconnect
io.disconnectSockets();
// make all Socket instances in the "room1" room disconnect (and discard the low-level connection)
io.in("room1").disconnectSockets(true);
// make all Socket instances in the "room1" room of the "admin" namespace disconnect
io.of("/admin").in("room1").disconnectSockets();
// this also works with a single socket ID
io.of("/admin").in(theSocketId).disconnectSockets();
fetchSockets
このメソッドは、一致するSocketインスタンスを返します。
// return all Socket instances of the main namespace
const sockets = await io.fetchSockets();
// return all Socket instances in the "room1" room of the main namespace
const sockets = await io.in("room1").fetchSockets();
// return all Socket instances in the "room1" room of the "admin" namespace
const sockets = await io.of("/admin").in("room1").fetchSockets();
// this also works with a single socket ID
const sockets = await io.in(theSocketId).fetchSockets();
上記の例のsockets
変数は、通常のSocketクラスのサブセットを公開するオブジェクトの配列です。
for (const socket of sockets) {
console.log(socket.id);
console.log(socket.handshake);
console.log(socket.rooms);
console.log(socket.data);
socket.emit(/* ... */);
socket.join(/* ... */);
socket.leave(/* ... */);
socket.disconnect(/* ... */);
}
data
属性は、Socket.IOサーバー間で情報を共有するために使用できる任意のオブジェクトです。
// server A
io.on("connection", (socket) => {
socket.data.username = "alice";
});
// server B
const sockets = await io.fetchSockets();
console.log(sockets[0].data.username); // "alice"
serverSideEmit
このメソッドを使用すると、マルチサーバー構成で、クラスターの他のSocket.IOサーバーにイベントを発行できます。
構文
io.serverSideEmit("hello", "world");
そして、受信側では
io.on("hello", (arg1) => {
console.log(arg1); // prints "world"
});
確認応答もサポートされています
// server A
io.serverSideEmit("ping", (err, responses) => {
console.log(responses[0]); // prints "pong"
});
// server B
io.on("ping", (cb) => {
cb("pong");
});
注意点
connection
、connect
、new_namespace
の文字列は予約されており、アプリケーションで使用することはできません。任意の数の引数を送信できますが、バイナリ構造は現在サポートされていません(引数の配列は
JSON.stringify
されます)。
例
io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });
- 他のSocket.IOサーバーが指定された遅延後に応答しない場合、確認応答コールバックはエラーで呼び出される可能性があります。
io.serverSideEmit("ping", (err, responses) => {
if (err) {
// at least one Socket.IO server has not responded
// the 'responses' array contains all the responses already received though
} else {
// success! the 'responses' array contains one object per other Socket.IO server in the cluster
}
});
イベント
サーバーインスタンスは1つのイベント(厳密には2つですが、connect
はconnection
のエイリアスです)を発行します。
connection
このイベントは、新しい接続時に発生します。最初の引数は、Socketインスタンスです。
io.on("connection", (socket) => {
// ...
});
完全なAPI
サーバーインスタンスによって公開される完全なAPIはこちらにあります。