The Server instance
The Server instance (often called io
in the code examples) has a few attributes that may be of use in your application.
It also inherits all the methods of the main namespace, like namespace.use()
(see here) or namespace.allSockets()
.
Server#engine
A reference to the underlying Engine.IO server.
It can be used to fetch the number of currently connected clients:
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; |
Or to generate a custom session ID (the sid
query parameter):
const uuid = require("uuid"); io.engine.generateId = (req) => { return uuid.v4(); // must be unique across all Socket.IO servers } |
As of [email protected]
, the Engine.IO server emits three special events:
-
initial_headers
: will be emitted just before writing the response headers of the first HTTP request of the session (the handshake), allowing you to customize them.
io.engine.on("initial_headers", (headers, req) => { headers["test"] = "123"; headers["set-cookie"] = "mycookie=456"; }); |
-
headers
: : will be emitted just before writing the response headers of each HTTP request of the session (including the WebSocket upgrade), allowing you to customize them.
io.engine.on("headers", (headers, req) => { headers["test"] = "789"; }); |
-
connection_error
: will be emitted when a connection is abnormally closed
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 }); |
Here is the list of possible error codes:
Code | Message |
---|---|
0 | “Transport unknown” |
1 | “Session ID unknown” |
2 | “Bad handshake method” |
3 | “Bad request” |
4 | “Forbidden” |
5 | “Unsupported protocol version” |
Utility methods
Some utility methods were added in Socket.IO v4.0.0 to manage the Socket instances and their rooms:
-
socketsJoin
: makes the matching socket instances join the specified rooms -
̀
socketsLeave
: makes the matching socket instances leave the specified rooms -
disconnectSockets
: makes the matching socket instances disconnect -
fetchSockets
: returns the matching socket instances
The serverSideEmit
method was added in Socket.IO v4.1.0.
Those methods share the same semantics as broadcasting, and the same filters apply:
io.of("/admin").in("room1").except("room2").local.disconnectSockets(); |
Which makes all Socket instances of the “admin” namespace
- in the “room1” room (
in("room1")
orto("room1")
) - except the ones in “room2” (
except("room2")
) - and only on the current Socket.IO server (
local
)
disconnect.
Please note that they are also compatible with the Redis adapter (starting with [email protected]
), which means that they will work across Socket.IO servers.
socketsJoin
This method makes the matching Socket instances join the specified rooms:
// 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
This method makes the matching Socket instances leave the specified rooms:
// 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
This method makes the matching Socket instances disconnect:
// 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
This method returns the matching Socket instances:
// return all Socket instances 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(); |
The sockets
variable in the example above is an array of objects exposing a subset of the usual Socket class:
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(/* ... */); } |
The data
attribute is an arbitrary object that can be used to share information between Socket.IO servers:
// 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
This method allows to emit events to the other Socket.IO servers of the cluster, in a multi-server setup.
Syntax:
io.serverSideEmit("hello", "world"); |
And on the receiving side:
io.on("hello", (arg1) => { console.log(arg1); // prints "world" }); |
Acknowledgements are supported too:
// server A io.serverSideEmit("ping", (err, responses) => { console.log(responses[0]); // prints "pong" }); // server B io.on("ping", (cb) => { cb("pong"); }); |
Notes:
-
the
connection
,connect
andnew_namespace
strings are reserved and cannot be used in your application. -
you can send any number of arguments, but binary structures are currently not supported (the array of arguments will be
JSON.stringify
-ed)
Example:
io.serverSideEmit("hello", "world", 1, "2", { 3: "4" }); |
- the acknowledgement callback might be called with an error, if the other Socket.IO servers do not respond after a given delay
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 } }); |
Events
The Server instance emits one single event (well, technically two, but connect
is an alias for connection
):
connection
This event is fired upon a new connection. The first argument is a Socket instance.
io.on("connection", (socket) => { // ... }); |
Complete API
The complete API exposed by the Server instance can be found here.
© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v4/server-instance