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 socket.io@4.1.0, 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 disconnectfetchSockets: 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 socket.io-redis@6.1.0), 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 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();
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,connectandnew_namespacestrings 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.