メインコンテンツへスキップ
バージョン: 4.x

Socketインスタンス (サーバーサイド)

Socketは、クライアントとやり取りするための基本クラスです。Node.jsのEventEmitterのすべてのメソッド(emitononceremoveListenerなど)を継承します。

Bidirectional communication between server and clientBidirectional communication between server and client

加えて

Socketインスタンスには、アプリケーションで役立つ可能性のあるいくつかの属性があります。

Socket#id

新しい接続ごとに、ランダムな20文字の識別子が割り当てられます。

この識別子はクライアント側の値と同期されます。

// server-side
io.on("connection", (socket) => {
console.log(socket.id); // ojIckSD2jqNzOqIrAGzL
});

// client-side
socket.on("connect", () => {
console.log(socket.id); // ojIckSD2jqNzOqIrAGzL
});
注意

接続状態の復旧が有効になっていない限り、id属性はアプリケーションで使用するべきではない(またはデバッグ目的でのみ使用する)**一時的な**IDであることに注意してください。理由は以下のとおりです。

  • このIDは、再接続のたびに再生成されます(たとえば、WebSocket接続が切断された場合や、ユーザーがページをリロードした場合)。
  • 異なるブラウザタブでは、異なるIDが2つ存在します。
  • サーバー側で特定のIDに対して保存されたメッセージキューはありません(つまり、クライアントが切断された場合、サーバーからこのIDに送信されたメッセージは失われます)。

代わりに、通常のセッションID(Cookieで送信するか、localStorageに保存してauthペイロードで送信)を使用してください。

こちらも参照してください

注: この識別子はSocket.IOコードベースのいくつかの部分で使用されているため、上書きすることはできません。

Socket#handshake

このオブジェクトには、Socket.IOセッションの開始時に発生するハンドシェイクに関する詳細が含まれています。

{
headers: /* the headers of the initial request */
query: /* the query params of the initial request */
auth: /* the authentication payload */
time: /* the date of creation (as string) */
issued: /* the date of creation (unix timestamp) */
url: /* the request URL string */
address: /* the ip of the client */
xdomain: /* whether the connection is cross-domain */
secure: /* whether the connection is secure */
}

{
"headers": {
"user-agent": "xxxx",
"accept": "*/*",
"host": "example.com",
"connection": "close"
},
"query": {
"EIO": "4",
"transport": "polling",
"t": "NNjNltH"
},
"auth": {
"token": "123"
},
"time": "Sun Nov 22 2020 01:33:46 GMT+0100 (Central European Standard Time)",
"issued": 1606005226969,
"url": "/socket.io/?EIO=4&transport=polling&t=NNjNltH",
"address": "::ffff:1.2.3.4",
"xdomain": false,
"secure": true
}

Socket#rooms

これは、Socketが現在所属しているルームへの参照です。

io.on("connection", (socket) => {
console.log(socket.rooms); // Set { <socket.id> }
socket.join("room1");
console.log(socket.rooms); // Set { <socket.id>, "room1" }
});

Socket#data

fetchSockets()ユーティリティメソッドと組み合わせて使用できる任意のオブジェクト

// server A
io.on("connection", (socket) => {
socket.data.username = "alice";
});

// server B
const sockets = await io.fetchSockets();
console.log(sockets[0].data.username); // "alice"

詳細についてはこちらをご覧ください。

Socket#conn

基盤となるEngine.IOソケットへの参照(こちらを参照)。

io.on("connection", (socket) => {
console.log("initial transport", socket.conn.transport.name); // prints "polling"

socket.conn.once("upgrade", () => {
// called when the transport is upgraded (i.e. from HTTP long-polling to WebSocket)
console.log("upgraded transport", socket.conn.transport.name); // prints "websocket"
});

socket.conn.on("packet", ({ type, data }) => {
// called for each packet received
});

socket.conn.on("packetCreate", ({ type, data }) => {
// called for each packet sent
});

socket.conn.on("drain", () => {
// called when the write buffer is drained
});

socket.conn.on("close", (reason) => {
// called when the underlying connection is closed
});
});

追加の属性

既存の属性を上書きしない限り、任意の属性をSocketインスタンスに追加して後で使用できます。

// in a middleware
io.use(async (socket, next) => {
try {
const user = await fetchUser(socket);
socket.user = user;
} catch (e) {
next(new Error("unknown user"));
}
});

io.on("connection", (socket) => {
console.log(socket.user);

// in a listener
socket.on("set username", (username) => {
socket.username = username;
});
});

Socketミドルウェア

これらのミドルウェアは、通常のミドルウェアとよく似ていますが、受信したパケットごとに呼び出される点が異なります。

socket.use(([event, ...args], next) => {
// do something with the packet (logging, authorization, rate limiting...)
// do not forget to call next() at the end
next();
});

nextメソッドは、エラーオブジェクトとともに呼び出すこともできます。その場合、イベントは登録されたイベントハンドラーに到達せず、代わりにerrorイベントが発行されます。

io.on("connection", (socket) => {
socket.use(([event, ...args], next) => {
if (isUnauthorized(event)) {
return next(new Error("unauthorized event"));
}
next();
});

socket.on("error", (err) => {
if (err && err.message === "unauthorized event") {
socket.disconnect();
}
});
});

注: この機能はサーバーサイドでのみ存在します。クライアントサイドでは、キャッチオールリスナーに関心があるかもしれません。

イベント

サーバーサイドでは、Socketインスタンスは2つの特別なイベントを発行します。

disconnect

このイベントは、切断時にSocketインスタンスによって発生します。

io.on("connection", (socket) => {
socket.on("disconnect", (reason) => {
// ...
});
});

考えられる理由のリストを次に示します。

理由説明
server namespace disconnectソケットはsocket.disconnect()で強制的に切断されました。
client namespace disconnectクライアントはsocket.disconnect()を使用してソケットを手動で切断しました。
server shutting downサーバーは、まあ、シャットダウンしています。
ping timeoutクライアントがpingTimeout遅延内でPONGパケットを送信しませんでした。
transport close接続が閉じられました(例:ユーザーが接続を失った、またはネットワークがWiFiから4Gに変更された)。
transport error接続でエラーが発生しました。
parse errorサーバーはクライアントから無効なパケットを受信しました。
forced closeサーバーはクライアントから無効なパケットを受信しました。
forced server closeクライアントが時間内に名前空間に参加しなかったため(connectTimeoutオプションを参照)、強制的に閉じられました。

disconnecting

このイベントはdisconnectに似ていますが、Socket#roomsセットがまだ空でない場合、少し早く発生します。

io.on("connection", (socket) => {
socket.on("disconnecting", (reason) => {
for (const room of socket.rooms) {
if (room !== socket.id) {
socket.to(room).emit("user has left", socket.id);
}
}
});
});

注: これらのイベントは、connectconnect_errornewListenerremoveListenerとともに、アプリケーションで使用すべきではない特別なイベントです。

// BAD, will throw an error
socket.emit("disconnect");

完全なAPI

Socketインスタンスによって公開される完全なAPIはこちらにあります。