web-dev-qa-db-fra.com

Comment mettre fin à une connexion WebSocket?

Est-il possible de mettre fin à une connexion websocket à partir d'un serveur sans fermer le serveur en entier? Si c'est le cas, comment puis-je y parvenir?

Remarque: J'utilise NodeJS en tant que module back-end et 'ws' websocket.

7
m87

Si vous voulez lancer tous les clients sans fermer le serveur, vous pouvez le faire:

for(const client of wss.clients)
{
  client.close();
}

vous pouvez également filtrer wss.clients également si vous souhaitez en rechercher un en particulier. Si vous souhaitez lancer un client dans le cadre de la logique de connexion (c'est-à-dire qu'il envoie des données incorrectes, etc.), vous pouvez procéder comme suit: 

let WebSocketServer = require("ws").Server;
let wss = new WebSocketServer ({ port: 8080 });

wss.on('connection', function connection(ws) {
    ws.send('something');
    ws.close(); // <- this closes the connection from the server
});

et avec un client de base 

"use strict";
const WebSocket = require("ws");
let ws = new WebSocket("ws://localhost:8080");
ws.onopen = () => {
    console.log("opened");
};
ws.onmessage = (m) => {
    console.log(m.data);
};
ws.onclose = () => {
    console.log("closed");
};

tu auras: 

d:/example/node client
opened
something
closed
6
Meirion Hughes

Donc, à cause d'une sorte d'omission dans la documentation concernant ws.close() et ws.terminate(), je pense que les solutions fournies dans les réponses fournies ne ferment pas les sockets correctement, dans certains cas, les gardant ainsi suspendues dans la boucle d'événement.

Comparez les deux méthodes suivantes du package ws:

  • ws.close()

Initialise la prise de contact étroite, envoie une image rapprochée à l'homologue et attend de recevoir une image rapprochée de l'homologue, après avoir envoyé le paquet FIN dans le but d'effectuer une fermeture de socket propre. Lorsque la réponse est reçue, le socket est détruit. Cependant, il existe une variable closeTimeout qui ne détruit le socket que dans le pire des cas, et qui pourrait éventuellement conserver le socket pendant 30 secondes supplémentaires, empêchant ainsi la fermeture en douceur avec votre délai d'attente personnalisé:

// ws/lib/WebSocket.js:21
const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly.
  • ws.terminate():

Détruit de force le socket sans fermer les trames ni les échanges de paquets fin, et le fait instantanément, sans aucun délai.

Arrêt brutal

Compte tenu de tout ce qui précède, le scénario "d'atterrissage brutal" serait le suivant:

wss.clients.forEach((socket) => {
  // Soft close
  socket.close();

  process.nextTick(() => {
    if ([socket.OPEN, socket.CLOSING].includes(socket.readyState)) {
      // Socket still hangs, hard close
      socket.terminate();
    }
  });
});

Arrêt progressif

Vous pouvez laisser à vos clients le temps de répondre, si vous pouviez vous permettre d’attendre un moment (mais pas 30 secondes):

// First sweep, soft close
wss.clients.forEach((socket) => {
  socket.close();
});

setTimeout(() => {
  // Second sweep, hard close
  // for everyone who's left
  wss.clients.forEach((socket) => {
    if ([socket.OPEN, socket.CLOSING].includes(socket.readyState)) {
      socket.terminate();
    }
  });
}, 10000);

Important: l'exécution correcte de la méthode close() émettra le code 1000 close pour l'événement close, tandis que terminate() signalera une fermeture anormale avec 1006 ( MDN WebSocket Close event ).

8
Damaged Organic

Selon la documentation de ws , vous devez appeler websocket.close() pour mettre fin à une connexion.

let server = new WebSocketServer(options);
server.on('connection', ws => {
  ws.close(); //terminate this connection
});
2
Lewis

Jus utiliser ws.close () de cette façon

var socketServer = new WebSocketServer();
socketServer.on('connection', function (ws) {
  ws.close(); //Close connecton for connected client ws
});

1
Denis Lisitskiy

Si vous utilisez var client = net.createConnection() pour créer le socket, vous pouvez utiliser client.destroy() pour le détruire.

Avec ws il devrait être:

var server = new WebSocketServer();
server.on('connection', function (socket) {
  // Do something and then
  socket.close(); //quit this connection
});
0
michelem