Aller au contenu principal
Version: 4.x

API côté serveur

Server

Server dans le diagramme de classe de la partie serveurServer dans le diagramme de classe de la partie serveur

Pages de documentation liées :

new Server(httpServer[, options])

import { createServer } from "http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server(httpServer, {
// options
});

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

httpServer.listen(3000);

La liste complète des options disponibles se trouve ici.

new Server(port[, options])

import { Server } from "socket.io";

const io = new Server(3000, {
// options
});

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

La liste complète des options disponibles se trouve ici.

new Server(options)

import { Server } from "socket.io";

const io = new Server({
// options
});

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

io.listen(3000);

La liste complète des options disponibles se trouve ici.

server.sockets

Un alias pour le Namespace principal (/).

io.sockets.emit("hi", "everyone");
// is equivalent to
io.of("/").emit("hi", "everyone");

server.serveClient([value])

Si value est true alors le serveur servira les fichiers client. Cette méthode n'a aucun effet après l'appel de listen().

Si aucun argument n'est fourni, cette méthode renvoie la valeur actuelle.

import { Server } from "socket.io";

const io = new Server();

io.serveClient(false);

io.listen(3000);

server.path([value])

Définit le chemin value sous lequel engine.io et les fichiers statiques seront servis. La valeur par défaut est /socket.io/.

Si aucun argument n'est fourni, cette méthode renvoie la valeur actuelle.

import { Server } from "socket.io";

const io = new Server();

io.path("/myownpath");
warning

La valeur path doit correspondre à celle côté client :

import { io } from "socket.io-client";

const socket = io({
path: "/myownpath"
});

server.adapter([value])

Définit l'Adapter qui sera utilisé par le serveur. Par défaut, il s'agira d'une instance d'Adapter basée sur la mémoire. Voir socket.io-adapter.

Si aucun argument n'est fourni, cette méthode renvoie la valeur actuelle.

import { Server } from "socket.io"; sur la
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";

const io = new Server();

const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();

io.adapter(createAdapter(pubClient, subClient));

// redis@3
io.listen(3000);

// redis@4
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.listen(3000);
});

server.attach(httpServer[, options])

Attache le serveur à un serveur HTTP Node.js avec les options fournies.

import { createServer } from "http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server();

io.attach(httpServer);

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

httpServer.listen(3000);

server.attach(port[, options])

Attache le serveur sur le port donné avec les options fournies.

import { Server } from "socket.io";

const io = new Server();

io.attach(3000);

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

server.attachApp(app[, options])

Associe le serveur Socket.IO à une application µWebSockets.js :

import { App } from "uWebSockets.js";
import { Server } from "socket.io";

const app = new App();
const io = new Server();

io.attachApp(app);

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

app.listen(3000, (token) => {
if (!token) {
console.warn("port already in use");
}
});

server.listen(httpServer[, options])

Synonyme de server.attach(httpServer[, options]).

server.listen(port[, options])

Synonyme de server.attach(port[, options]).

server.on(eventName, listener)

Héritée de la classe EventEmitter.

Ajoute la fonction listener à la fin du tableau des auditeurs pour l'événement nommé eventName.

Événements disponibles :

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

server.bind(engine)

Utilisation avancée uniquement. Lie le serveur à une instance Engine.IO (ou API compatible).

import { Server } from "socket.io";
import { Server as Engine } from "engine.io";

const engine = new Engine();
const io = new Server();

io.bind(engine);

engine.listen(3000);

server.onconnection(socket)

Utilisation avancée uniquement. Crée un nouveau client Socket.IO à partir d'une connexion Engine.IO (ou API compatible).

import { Server } from "socket.io";
import { Server as Engine } from "engine.io";

const engine = new Engine();
const io = new Server();

engine.on("connection", (socket) => {
io.onconnection(socket);
});

engine.listen(3000);

server.of(nsp)

Initialise et récupère le Namespace à partir de son identifiant nsp. Si le Namespace a déjà été initialisé, il est retourné directement.

const adminNamespace = io.of("/admin");

Une expression régulière ou une fonction peut également être fournie, afin de créer un Namespace de manière dynamique :

const dynamicNsp = io.of(/^\/dynamic-\d+$/).on("connection", (socket) => {
const newNamespace = socket.nsp; // newNamespace.name === "/dynamic-101"

// émission à tous les clients dans le namespace enfant donné
newNamespace.emit("hello");
});

// côté client
const socket = io("/dynamic-101");

// émission à tous les clients dans chaque namespace enfant
dynamicNsp.emit("hello");

// utilisation d'un middleware commun à tous les namespaces enfant
dynamicNsp.use((socket, next) => { /* ... */ });

Avec une function :

io.of((name, query, next) => {
// la méthode checkToken doit retourner un booléen indiquant si le client est autorisé à se connecter
next(null, checkToken(query.token));
}).on("connection", (socket) => { /* ... */ });

server.close([callback])

Ferme le serveur Socket.IO et déconnecte tous les clients. L'argument callback est facultatif et sera invoqué lorsque toutes les connexions seront fermées.

info

Cela ferme également le serveur HTTP sous-jacent.

import { createServer } from "http";
import { Server } from "socket.io";

const PORT = 3030;
const io = new Server(PORT);

io.close();

const httpServer = createServer();

httpServer.listen(PORT); // PORT peut être réutilisé

io.attach(httpServer);
note

La fermeture du serveur HTTP sous-jacent n'est pas suffisante, car cela empêchera uniquement le serveur d'accepter de nouvelles connexions, mais les clients connectés via WebSocket ne seront pas déconnectés immédiatement.

Référence : https://nodejs.org/api/http.html#serverclosecallback

server.engine

Une référence au serveur Engine.IO sous-jacent. Voir ici.

server.socketsJoin(rooms)

Ajoutée en v4.0.0

Alias de io.of("/").socketsJoin(rooms).

// toutes les instances de Socket rejoignent la room "room1"
io.socketsJoin("room1");

// toutes les instances de Socket présentes dans la room "room1" rejoignent les rooms "room2" et "room3"
io.in("room1").socketsJoin(["room2", "room3"]);

// cela fonctionne également avec un socket ID
io.in(theSocketId).socketsJoin("room1");

Voir ici.

server.socketsLeave(rooms)

Ajoutée en v4.0.0

Alias de io.of("/").socketsLeave(rooms).

// toutes les instances de Socket quittent la room "room1"
io.socketsLeave("room1");

// toutes les instances de Socket présentes dans la room "room1" quittent les rooms "room2" et "room3"
io.in("room1").socketsLeave(["room2", "room3"]);

// cela fonctionne également avec un socket ID
io.in(theSocketId).socketsLeave("room1");

Voir ici.

server.disconnectSockets([close])

Ajoutée en v4.0.0

Alias de io.of("/").disconnectSockets(close).

// toutes les instances de Socket sont déconnectées
io.disconnectSockets();

// toutes les instances de Socket présentes dans la room "room1" sont déconnectées (et la connexion de bas niveau est fermée)
io.in("room1").disconnectSockets(true);

Voir ici.

server.fetchSockets()

Ajoutée en v4.0.0

Alias de io.of("/").fetchSocket().

// récupère tous les sockets dans le namespace principal
const sockets = await io.fetchSockets();

// récupère tous les sockets dans la room "room1" du namespace principal
const sockets = await io.in("room1").fetchSockets();

Exemple d'utilisation :

io.on("connection", (socket) => {
const userId = computeUserId(socket);

socket.join(userId);

socket.on("disconnect", async () => {
const sockets = await io.in(userId).fetchSockets();
if (socket.length === 0) {
// plus de connexion active pour l'utilisateur donné
}
});
});

Voir ici.

server.serverSideEmit(eventName[, ...args][, ack])

Ajoutée en v4.1.0

Alias de : io.of("/").serverSideEmit(/* ... */);

Événement : connection

  • socket (Socket) inst

Émis lors d'une connexion.

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

Événement : connect

Synonyme de Événement : "connection".

Événement : new_namespace

Émis lorsqu'un nouveau Namespace est créé :

io.on("new_namespace", (namespace) => {
// ...
});

Cela peut être utile par exemple :

  • pour attacher un middleware commun à tous les Namespaces
io.on("new_namespace", (namespace) => {
namespace.use(myMiddleware);
});
io.of(/\/nsp-\w+/);

io.on("new_namespace", (namespace) => {
console.log(namespace.name);
});

Namespace

Namespace dans le diagramme de classe de la partie serveurNamespace dans le diagramme de classe de la partie serveur

// TODO Représente un ensemble de connexions connectés sous une portée donnée identifiée par un nom de chemin (ex : /chat).

Represents a pool of sockets connected under a given scope identified by a pathname (eg: /chat).

Plus de détails ici.

namespace.name

L'identifiant du Namespace.

namespace.sockets

Une Map de Sockets qui sont actuellement connectés à ce Namespace.

// nombre de sockets dans ce namespace (pour ce serveur)
const socketCount = io.of("/admin").sockets.size;

namespace.adapter

L'Adapter utilisé par le Namespace.

Note : l'Adapter pour le Namespace principal est accessible via io.of("/").adapter.

Plus d'informations à ce sujet ici.

const adapter = io.of("/my-namespace").adapter;

namespace.to(room)

History
VersionChanges
v4.0.0Ajout de la possibilité de fournir un tableau de Rooms.
v1.0.0Implémentation initiale.

Définit un modificateur pour une émission d'événement ultérieure selon laquelle l'événement ne sera diffusé qu'aux clients qui ont rejoint la Room donnée.

Pour émettre vers plusieurs Rooms, vous pouvez appeler to plusieurs fois.

const io = require("socket.io")();
const adminNamespace = io.of("/admin");

adminNamespace.to("level1").emit("an event", { some: "data" });

// rooms multiples
io.to("room1").to("room2").emit(/* ... */);

// ou avec un tableau
io.to(["room1", "room2"]).emit(/* ... */);

namespace.in(room)

Ajoutée en v1.0.0

Synonyme de namespace.to(room).

namespace.except(rooms)

Ajoutée en v4.0.0

Définit un modificateur pour une émission d'événement ultérieure selon laquelle l'événement ne sera diffusé qu'aux clients qui n'ont pas rejoint les Rooms données.

// à tous les clients exceptés ceux dans la room "room1"
io.except("room1").emit(/* ... */);

// à tous les clients présents dans la room "room2" exceptés ceux dans la room "room3"
io.to("room2").except("room3").emit(/* ... */);

namespace.emit(eventName[, ...args])

Émet un événement à tous les clients connectés dans le Namespace donné.

io.emit("un événement envoyé à tous les clients connectés"); // namespace principal

const chat = io.of("/chat");
chat.emit("un événement envoyé à tous les clients connectés dans le namespace 'chat'");
info

Les accusés de réception ne sont actuellement pas pris en charge lors de l'émission à partir d'un Namespace.

namespace.allSockets()

  • Retourne Promise<Set<SocketId>>

Obtient une liste des ID de Socket connectés à ce Namespace (pour tous les serveurs du cluster, le cas échéant).

// tous les sockets du namespace principal
const ids = await io.allSockets();

// tous les sockets dans la room "user:1234" du namespace principal
const ids = await io.in("user:1234").allSockets();

// tous les sockets du namespace "chat"
const ids = await io.of("/chat").allSockets();

// tous les sockets dans la room "general" du namespace "chat"
const ids = await io.of("/chat").in("general").allSockets();

namespace.use(fn)

Ajoute un middleware, qui sera exécuté pour chaque Socket entrant, et reçoit comme paramètres le Socket et une fonction pour différer éventuellement l'exécution au prochain middleware enregistré.

Les erreurs transmises aux fonctions rappels (« callback ») du middleware sont envoyées sous forme de paquets spéciaux connect_error aux clients.

Serveur

io.use((socket, next) => {
const err = new Error("pas autorisé");
err.data = { content: "Merci de réessayer plus tard" }; // détails additionnels
next(err);
});

Client

socket.on("connect_error", err => {
console.log(err instanceof Error); // true
console.log(err.message); // "pas autorisé"
console.log(err.data); // { content: "Merci de réessayer plus tard" }
});

Plus d'informations à ce sujet ici.

namespace.socketsJoin(rooms)

Ajoutée en v4.0.0

Fait en sorte que les instances Socket correspondantes rejoignent les Rooms spécifiées :

// tous les sockets rejoignent la room "room1"
io.socketsJoin("room1");

// tous les sockets présents dans la room "room1" rejoignent les rooms "room2" et "room3"
io.in("room1").socketsJoin(["room2", "room3"]);

// tous les sockets présents dans la room "room1" du namespace "admin" rejoignent la room "room2"
io.of("/admin").in("room1").socketsJoin("room2");

// cela fonctionne également avec un seul ID de socket
io.in(theSocketId).socketsJoin("room1");

Plus d'informations à ce sujet ici.

namespace.socketsLeave(rooms)

Ajoutée en v4.0.0

Fait en sorte que les instances Socket correspondantes quittent les Rooms spécifiées :

// tous les sockets quittent la room "room1"
io.socketsLeave("room1");

// tous les sockets présents dans la room "room1" quittent les rooms "room2" et "room3"
io.in("room1").socketsLeave(["room2", "room3"]);

// tous les sockets présents dans la room "room1" du namespace "admin" quittent la room "room2"
io.of("/admin").in("room1").socketsLeave("room2");

// cela fonctionne également avec un seul ID de socket
io.in(theSocketId).socketsLeave("room1");

namespace.disconnectSockets([close])

Ajoutée en v4.0.0

  • close <boolean> s'il faut clore la connexion sous-jacente
  • Retourne void

Déconnecte les Sockets correspondants.

// tous les sockets sont déconnectés
io.disconnectSockets();

// tous les sockets présents dans la room "room1" sont déconnectés (et la connexion bas niveau est close)
io.in("room1").disconnectSockets(true);

// tous les sockets présents dans la room "room1" du namespace "admin" sont déconnectés
io.of("/admin").in("room1").disconnectSockets();

// cela fonctionne également avec un seul ID de socket
io.of("/admin").in(theSocketId).disconnectSockets();

namespace.fetchSockets()

Ajoutée en v4.0.0

Récupère les Sockets correspondants :

// récupère tous les sockets dans le namespace principal
const sockets = await io.fetchSockets();

// récupère tous les sockets présents dans la room "room1" du namespace principal
const sockets = await io.in("room1").fetchSockets();

// récupère tous les sockets présents dans la room "room1" du namespace "admin"
const sockets = await io.of("/admin").in("room1").fetchSockets();

// cela fonctionne également avec un seul ID de socket
const sockets = await io.in(theSocketId).fetchSockets();

La variable sockets dans l'exemple ci-dessus est un tableau d'objets exposant un sous-ensemble de la classe Socket habituelle :

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(/* ... */);
}

L'attribut data est un objet arbitraire qui peut être utilisé pour partager des informations entre les serveurs Socket.IO :

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

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

Cette méthode (ainsi que socketsJoin, socketsLeave et disconnectSockets) est compatible avec l'Adapter Redis (à partir de socket.io-redis@6.1.0), ce qui signifie qu'ils fonctionneront également pour un cluster de serveurs Socket.IO.

namespace.serverSideEmit(eventName[, ...args][, ack])

Ajoutée en v4.1.0

Envoie un message aux autres serveurs Socket.IO du cluster.

Syntaxe :

io.serverSideEmit("bonjour", "ô monde");

Et côté réception :

io.on("bonjour", (arg1) => {
console.log(arg1); // affiche "ô monde"
});

Les accusés de réception sont également pris en charge :

// serveur A
io.serverSideEmit("ping", (err, responses) => {
console.log(responses[0]); // affiche "pong"
});

// serveur B
io.on("ping", (cb) => {
cb("pong");
});

Notes :

  • les chaînes de caractères connection, connect et new_namespace sont réservées et ne peuvent pas être utilisées dans votre application.

  • vous pouvez envoyer n'importe quel nombre d'arguments, mais les structures binaires ne sont actuellement pas prises en charge (le tableau d'arguments sera JSON.stringify-é)

Exemple :

io.serverSideEmit("bonjour", "ô monde", 1, "2", { 3: "4" });
  • la fonction rappel peut être invoquée avec une erreur, si les autres serveurs Socket.IO ne répondent pas après un délai donné
io.serverSideEmit("ping", (err, responses) => {
if (err) {
// au moins un serveur Socket.IO n'a pas répondu dans le temps imparti
// mais le tableau 'responses' contient toutes les réponses déjà reçues
} else {
// Succès ! le tableau 'responses' contient un objet pour chaque serveur Socket.IO dans le cluster
}
});

Événement : 'connection'

Émis lors d'une connexion :

// namespace principal
io.on("connection", (socket) => {
// ...
});

// namespace spécifique
io.of("/admin").on("connection", (socket) => {
// ...
});

Événement : 'connect'

Synonyme de Événement : "connection".

Drapeau : 'volatile'

Définit un modificateur pour une émission d'événement ultérieure selon lequel l'événement peut être perdu si les clients ne sont pas prêts à recevoir des messages (à cause de la lenteur du réseau ou d'autres problèmes, ou parce qu'ils sont connectés via une longue interrogation et sont au milieu d'un cycle de réponse).

io.volatile.emit("an event", { some: "data" }); // les clients pourront peut-être le recevoir

Drapeau : 'local'

Définit un modificateur pour une émission d'événement ultérieure selon lequel l'événement ne sera diffusé qu'au nœud actuel (lors de la mise en place d'un cluster).

io.local.emit("an event", { some: "data" });

Socket

Socket dans le diagramme de classe de la partie serveurSocket dans le diagramme de classe de la partie serveur

A Socket is the fundamental class for interacting with browser clients. A Socket belongs to a certain Namespace (by default /) and uses an underlying Client to communicate.

It should be noted the Socket doesn't relate directly to the actual underlying TCP/IP socket and it is only the name of the class.

Within each Namespace, you can also define arbitrary channels (called room) that the Socket can join and leave. That provides a convenient way to broadcast to a group of Sockets (see Socket#to below).

The Socket class inherits from EventEmitter. The Socket class overrides the emit method, and does not modify any other EventEmitter method. All methods documented here which also appear as EventEmitter methods (apart from emit) are implemented by EventEmitter, and documentation for EventEmitter applies.

More information can be found here.

socket.id

Un identifiant unique pour la session.

socket.rooms

Un ensemble de chaînes de caractères identifiant les Rooms dans lesquelles se trouve ce Socket.

io.on("connection", (socket) => {

console.log(socket.rooms); // Set { <socket.id> }

socket.join("room1");

console.log(socket.rooms); // Set { <socket.id>, "room1" }

});

socket.client

Une référence à l'objet Client sous-jacent.

socket.conn

  • <engine.Socket>

Une référence au client de connexion sous-jacent (objet Socket côté Engine.IO). Cela permet d'accéder à la couche de transport qui gère la connexion TCP.

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

socket.conn.once("upgrade", () => {
// émis lorsque le transport est mis à jour (exemple : de HTTP long-polling vers WebSocket)
console.log("upgraded transport", socket.conn.transport.name); // affiche "websocket"
});

socket.conn.on("packet", ({ type, data }) => {
// émis pour chaque paquet reçu
});

socket.conn.on("packetCreate", ({ type, data }) => {
// appelé pour chaque paquet envoyé
});

socket.conn.on("drain", () => {
// appelé lorsque le tampon d'écriture est vidé
});

socket.conn.on("close", (reason) => {
// appelé lorsque la connexion sous-jacente est fermée
});
});

socket.request

Une référence à la première requête HTTP du client. Utile pour accéder aux en-têtes HTTP tels que Cookie ou User-Agent.

import { parse } from "cookie";

io.on("connection", (socket) => {
const cookies = parse(socket.request.headers.cookie || "");
});

socket.handshake

Les détails de la poignée de main (« handshake ») :

{
headers: /* les en-têtes envoyés dans le cadre de la poignée de main */,
time: /* la date de création (sous forme de chaîne de caractère) */,
address: /* l'adresse IP du client */,
xdomain: /* si la connexion est interdomaine */,
secure: /* si la connexion est sécurisée */,
issued: /* la date de création (sous forme d'horodatage unix) */,
url: /* l'URL de la première requête HTTP */,
query: /* les paramètres de requête de la première requête HTTP */,
auth: /* les données d'authentification */
}

Utilisation :

io.use((socket, next) => {
let handshake = socket.handshake;
// ...
});

io.on("connection", (socket) => {
let handshake = socket.handshake;
// ...
});

socket.use(fn)

History
VersionChangements
v3.0.5Restauration de la première implémentation.
v3.0.0Suppression en facteur de socket.onAny().
v1.7.2L'événement error est envoyé directement au client.
v1.6.0Première implémentation.

Ajoute un middleware, qui sera exécuté pour chaque paquet entrant et reçoit en paramètre le paquet et une fonction pour différer éventuellement l'exécution au prochain middleware enregistré.

Les erreurs transmises à la fonction rappel (« callback ») du middleware sont ensuite émises en tant qu'événements "error" côté serveur :

io.on("connection", (socket) => {
socket.use(([event, ...args], next) => {
if (isUnauthorized(event)) {
return next(new Error("unauthorized event"));
}
// ne pas oublier d'appeler next()
next();
});

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

socket.send([...args][, ack])

Envoie un événement message. Voir socket.emit(eventName[, ...args][, ack]).

socket.emit(eventName[, ...args][, ack])

(surcharge EventEmitter.emit)

Émet un événement. Tout autre paramètre peut être inclus. Toutes les structures de données sérialisables sont prises en charge, y compris Buffer et TypedArray.

socket.emit("hello", "world");
socket.emit("with-binary", 1, "2", { 3: "4", 5: Buffer.from([6]) });

L'argument ack est facultatif et sera appelé avec l'accusé de réception du client.

Server

io.on("connection", (socket) => {
socket.on("bonjour", (arg, callback) => {
console.log(arg); // "ô monde"
callback("bien reçu !");
});
});

Client

socket.emit("bonjour", "ô monde", (response) => {
console.log(response); // "bien reçu !"
});

socket.on(eventName, callback)

Héritée de la classe EventEmitter.

Ajoute un nouvel auditeur pour l'événement donné.

socket.on("news", (data) => {
console.log(data);
});

// avec plusieurs arguments
socket.on("news", (arg1, arg2, arg3) => {
// ...
});

// avec un accusé de réception
socket.on("news", (data, callback) => {
callback(0);
});

socket.once(eventName, listener)

socket.removeListener(eventName, listener)

socket.removeAllListeners([eventName])

socket.eventNames()

Héritées de la classe EventEmitter (ainsi que d'autres méthodes non mentionnées ici). Cf. la documentation Node.js du module events.

socket.onAny(callback)

Ajoute un nouvel auditeur attrape-tout (« catch-all »).

socket.onAny((event, ...args) => {
console.log(`reçu ${event}`);
});

socket.prependAny(callback)

Ajoute un nouvel auditeur attrape-tout. La fonction est ajoutée au début du tableau des auditeurs.

socket.prependAny((event, ...args) => {
console.log(`got ${event}`);
});

socket.offAny([listener])

Supprime l'auditeur attrape-tout donné. Si aucun auditeur n'est fourni, tous les auditeurs attrape-tout sont supprimés.

const myListener = () => { /* ... */ };

socket.onAny(myListener);

// then, later
socket.offAny(myListener);

socket.offAny();

socket.listenersAny()

Renvoie le tableau des auditeurs attrape-tout.

const listeners = socket.listenersAny();

socket.join(room)

Ajoute le Socket à la Room ou au tableau de Rooms.

io.on("connection", (socket) => {
socket.join("room 237");

console.log(socket.rooms); // Set { <socket.id>, "room 237" }

socket.join(["room 237", "room 238"]);

io.to("room 237").emit("a new user has joined the room"); // diffusion à tous ceux présents dans la room
});

Les mécanismes de connexion des Rooms sont gérés par l'Adapter qui a été configuré (voir Server#adapter ci-dessus), par défaut socket.io-adapter.

Par commodité, chaque Socket rejoint automatiquement une Room identifiée par son identifiant (voir Socket#id). Cela facilite la diffusion de messages vers d'autres Sockets :

io.on("connection", (socket) => {
socket.on("say to someone", (id, msg) => {
// envoyer un message privé au socket avec l'identifiant donné
socket.to(id).emit("my message", msg);
});
});

socket.leave(room)

Supprime le Socket de la Room.

io.on("connection", (socket) => {
socket.leave("room 237");

io.to("room 237").emit(`user ${socket.id} has left the room`);
});
info

Le Socket est supprimé automatiquement de toutes les Rooms lors de la déconnexion.

socket.to(room)

History
VersionChanges
v4.0.0Ajout de la possibilité de passer un tableau de Rooms.
v1.0.0Première implémentation.

Définit un modificateur pour une émission d'événement ultérieure selon lequel l'événement ne sera diffusé qu'aux clients qui ont rejoint la Room donnée (le Socket lui-même étant exclu).

Pour émettre vers plusieurs Rooms, vous pouvez appeler to plusieurs fois.

io.on("connection", (socket) => {

// vers une room
socket.to("others").emit("an event", { some: "data" });

// vers plusieurs rooms
socket.to("room1").to("room2").emit("hello");

// avec un tableau
socket.to(["room1", "room2"]).emit("hello");

// message privé vers un autre socket
socket.to(/* another socket id */).emit("hey");

// Attention ! `socket.to(socket.id).emit()` ne fonctionnera pas. Merci d'utiliser `socket.emit()` à la place.
});
info

Les accusés de réception ne sont actuellement pas pris en charge par la diffusion d'événements.

socket.in(room)

Ajoutée en v1.0.0

Synonyme de socket.to(room).

socket.except(rooms)

Ajoutée en v4.0.0

Définit un modificateur pour une émission d'événement ultérieure selon lequel l'événement ne sera diffusé qu'aux clients qui n'ont pas rejoint les Rooms données (le Socket lui-même étant exclu).

// à tous les clients sauf ceux dans la room "room1" (ainsi que l'émetteur)
socket.broadcast.except("room1").emit(/* ... */);

// même chose qu'au dessus
socket.except("room1").emit(/* ... */);

// à tous les clients dans la room "room4" sauf ceux dans la room "room1" (ainsi que l'émetteur)
socket.to("room4").except("room5").emit(/* ... */);

socket.compress(value)

  • value <boolean> whether to following packet will be compressed
  • Retourne Socket pour l'enchaînement

Définit un modificateur pour une émission d'événement ultérieure selon lequel les données d'événement ne seront compressées que si la valeur est "true". La valeur par défaut est true lorsque vous n'appelez pas la méthode.

io.on("connection", (socket) => {
socket.compress(false).emit("uncompressed", "that's rough");
});

socket.timeout(value)

Ajoutée en v4.4.0

Définit un modificateur pour une émission d'événement ultérieure selon lequel la fonction rappel (« callback ») sera invoquée avec une erreur lorsqu'un certain nombre de millisecondes se seront écoulées sans accusé de réception de la part du client :

socket.timeout(5000).emit("my-event", (err) => {
if (err) {
// le client n'a pas accusé réception de l'événement dans le délai imparti
}
});

socket.disconnect(close)

Déconnecte ce Socket. Si la valeur de close est true, ferme la connexion sous-jacente. Sinon, il déconnecte unique le Namespace.

io.on("connection", (socket) => {
setTimeout(() => socket.disconnect(true), 5000);
});

Drapeau : 'broadcast'

Définit un modificateur pour une émission d'événement ultérieure selon lequel l'événement sera diffusé à tous les Sockets (en excluant le Socket émetteur).

io.on("connection", (socket) => {
socket.broadcast.emit("an event", { some: "data" }); // tous les clients le reçoivent sauf l'émetteur
});

Drapeau : 'volatile'

Définit un modificateur pour une émission d'événement ultérieure selon lequel l'événement peut être perdu si les clients ne sont pas prêts à recevoir des messages (à cause de la lenteur du réseau ou d'autres problèmes, ou parce qu'ils sont connectés via une longue interrogation et sont au milieu d'un cycle de réponse).

io.on("connection", (socket) => {
socket.volatile.emit("an event", { some: "data" }); // le client le recevra peut-être
});

Événement : 'disconnect'

  • reason <string> the reason of the disconnection (either client or server-side)

Émis lors de la déconnexion.

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

Raisons possibles :

RaisonDescription
server namespace disconnectLe Socket a été manuellement déconnecté avec la méthode socket.disconnect()
client namespace disconnectLe client a manuellement déconnecté le Socket avec la méthode socket.disconnect()
server shutting downLe serveur est en train de s'arrêter
ping timeoutLe client n'a pas envoyé de paquet PONG dans le délai pingTimeout imparti
transport closeLa connexion a été interrompue (exemple : l'utilisateur a perdu la connexion, ou le réseau est passé du WiFi à la 4G)
transport errorLa connexion a rencontré une erreur

Événement : 'disconnecting'

  • reason <string> the reason of the disconnection (either client or server-side)

Émis lorsque le client est sur le point d'être déconnecté (mais qu'il n'a pas encore quitté ses Rooms).

io.on("connection", (socket) => {
socket.on("disconnecting", (reason) => {
console.log(socket.rooms); // Set { ... }
});
});

Remarque : ces événements, ainsi que connect, connect_error, newListener et removeListener, sont des événements spéciaux qui ne doivent pas être utilisés dans votre application :

// INCORRECT, une exception sera levée 
socket.emit("disconnect");

Client

Client dans le diagramme de classe de la partie serveurClient dans le diagramme de classe de la partie serveur

La classe Client représente une connexion de transport entrante (engine.io). Un Client peut être associé à plusieurs Sockets multiplexés appartenant à différents Namespaces.

client.conn

  • <engine.Socket>

Une référence au client de connexion sous-jacent (objet Socket côté Engine.IO)

client.request

Une référence à la première requête HTTP du client. Utile pour accéder aux en-têtes HTTP tels que Cookie ou User-Agent.

Engine

Le serveur Engine.IO, qui gère les connexions WebSocket / HTTP long-polling. Plus d'informations ici.

Son code source se trouve ici : https://github.com/socketio/engine.io

engine.clientsCount

Ajoutée en v1.0.0

Le nombre de clients actuellement connectés.

const count = io.engine.clientsCount;
// peut potentiellement être similaire au nombre de sockets dans le namespace principal, selon votre utilisation
const count2 = io.of("/").sockets.size;

engine.generateId

La fonction utilisée pour générer un nouvel ID de session. Utilise base64id par défaut.

const uuid = require("uuid");

io.engine.generateId = () => {
return uuid.v4(); // doit être unique au sein d'un cluster de serveurs Socket.IO
}

engine.handleUpgrade(request, socket, head)

Ajoutée en v1.0.0

Cette méthode peut être utilisée pour injecter une mise à niveau HTTP.

Exemple avec un serveur Socket.IO et un serveur WebSocket classique :

import { createServer } from "http";
import { Server as WsServer } from "ws";
import { Server } from "socket.io";

const httpServer = createServer();
const wss = new WsServer({ noServer: true });
const io = new Server(httpServer);

httpServer.removeAllListeners("upgrade");

httpServer.on("upgrade", (req, socket, head) => {
if (req.url === "/") {
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit("connection", ws, req);
});
} else if (req.url.startsWith("/socket.io/")) {
io.engine.handleUpgrade(req, socket, head);
} else {
socket.destroy();
}
});

httpServer.listen(3000);

Événement : 'initial_headers'

Ajoutée en v4.1.0

Cet événement sera émis juste avant d'écrire les en-têtes de réponse de la première requête HTTP de la session (la poignée de main), vous permettant de les personnaliser.

import { serialize } from "cookie";

io.engine.on("initial_headers", (headers, request) => {
headers["set-cookie"] = serialize("uid", "1234", { sameSite: "strict" });
});

Événement : 'headers'

Ajoutée en v4.1.0

Cet événement sera émis juste avant d'écrire les en-têtes de réponse de chaque requête HTTP de la session (y compris la mise à jour WebSocket), vous permettant de les personnaliser.

import { serialize, parse } from "cookie";

io.engine.on("headers", (headers, request) => {
if (!request.headers.cookie) return;
const cookies = parse(request.headers.cookie);
if (!cookies.randomId) {
headers["set-cookie"] = serialize("randomId", "abc", { maxAge: 86400 });
}
});

Événement : 'connection_error'

Ajoutée en v4.1.0

io.engine.on("connection_error", (err) => {
console.log(err.req); // la requête
console.log(err.code); // le code d'erreur, par exemple "1"
console.log(err.message); // le message d'erreur, par exemple "Session ID unknown"
console.log(err.context); // un contexte d'erreur supplémentaire
});

Cet événement sera émis lorsqu'une connexion est anormalement fermée. Voici la liste des codes d'erreur possibles :

CodeMessage
0"Transport unknown"
1"Session ID unknown"
2"Bad handshake method"
3"Bad request"
4"Forbidden"
5"Unsupported protocol version"