相关文章推荐
八块腹肌的绿茶  ·  Migrating from Indy 9 ...·  1 年前    · 
愉快的眼镜  ·  ModuleNotFoundError:当我 ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Is it possible to terminate a websocket connection from server without closing the entire server? If it is then, how can I achieve it?

Note: I'm using NodeJS as back-end and 'ws' websocket module.

Welcome to Stack Overflow! You can take the tour first and learn How to Ask a good question and create a Minimal, Complete, and Verifiable example. It will be easier for us to help you. Alexandre Tranchant Dec 10, 2016 at 9:44

So because of some sort of omission in the documentation regarding ws.close() and ws.terminate() I think the solutions in provided answers won't close the sockets gracefully in some cases, thus keeping them hanging in the Event Loop.

Compare the next two methods of ws package:

  • ws.close() :
  • Initializes close handshake, sending close frame to the peer and awaiting to receive close frame from the peer, after that sending FIN packet in attempt to perform a clean socket close. When answer received, the socket is destroyed. However, there is a closeTimeout that will destroy socket only as a worst case scenario, and it potentially could keep socket for additional 30 seconds, preventing the graceful exit with your custom timeout:

    // ws/lib/WebSocket.js:21
    const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly.
    
  • ws.terminate():
  • Forcibly destroys the socket without closing frames or fin packets exchange, and does it instantly, without any timeout.

    Hard shutdown

    Considering all of the above, the "hard landing" scenario would be as follows:

    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();
    

    Soft shutdown

    You can give your clients some time to respond, if you could allow yourself to wait for a while (but not 30 seconds):

    // 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);
                    This answer is incredibly useful and insightful. Solved a major Websocket connection issue for me.
    – Mustafa Alammar
                    Jun 28, 2021 at 19:31
                    When you say "...keeping them hanging in the Event Loop" do you mean the client event loop or the server's event loop?
    – sam
                    Jan 24 at 20:22
    

    If you want to kick ALL clients without closing the server you can do this:

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

    you can also filter wss.clients too if you want to look for one in particular. If you want to kick a client as part of the connection logic (i.e. it sends bad data etc), you can do this:

    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
    

    and with a basic client

    "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");
    

    you'll get:

    d:/example/node client
    opened
    something
    closed
    

    According to the ws documentation, you need to call websocket.close() to terminate a connection.

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

    Just use ws.close() in this way.

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

    If you use var client = net.createConnection() to create the socket you can use client.destroy() to destroy it.

    With ws it should be:

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

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.