【问题标题】:How to terminate a WebSocket connection?如何终止 WebSocket 连接?
【发布时间】:2020-08-10 14:42:07
【问题描述】:

是否可以在不关闭整个服务器的情况下终止来自服务器的 websocket 连接?如果是的话,我该如何实现呢?

注意:我使用 NodeJS 作为后端和 'ws' websocket 模块。

【问题讨论】:

标签: javascript node.js


【解决方案1】:

因此,由于有关ws.close()ws.terminate() 的文档中存在某种遗漏,我认为提供的答案中的解决方案在某些情况下不会优雅地关闭套接字,从而使它们保持在事件循环中。

比较ws包的下两种方法:

  • ws.close()

初始化关闭握手,向对端发送关闭帧并等待从对端接收关闭帧,然后发送 FIN 数据包以尝试执行干净的套接字关闭。收到答复后,套接字被销毁。但是,有一个 closeTimeout 只会在最坏的情况下破坏套接字,并且它可能会使套接字再保持 30 秒,从而阻止您自定义超时的正常退出:

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

在不关闭帧或fin数据包交换的情况下强制销毁套接字,并且立即执行,没有任何超时。

硬关机

考虑到以上所有因素,“硬着陆”情况如下:

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

软关机

如果您可以让自己等待一段时间(但不是 30 秒),您可以给您的客户一些时间做出回应:

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

重要提示:正确执行close()方法会为close事件发出1000关闭代码,而terminate()会用1006MDN WebSocket Close event)发出异常关闭信号。

【讨论】:

  • 这个答案比我觉得选择的答案好!
  • 为什么我在这里找到了这个解释,但在文档中却没有?
  • 这个答案非常有用且富有洞察力。为我解决了一个主要的 Websocket 连接问题。
【解决方案2】:

如果你想在不关闭服务器的情况下踢掉所有客户端,你可以这样做:

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

如果您想特别寻找一个,也可以过滤wss.clients。如果您想将客户端作为连接逻辑的一部分(即它发送错误数据等),您可以这样做:

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

和一个基本的客户

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

你会得到:

d:/example/node client
opened
something
closed

【讨论】:

  • wss 本身呢,例如不需要移除事件监听器吗?
【解决方案3】:

根据ws documentation,需要调用websocket.close()来终止连接。

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

【讨论】:

    【解决方案4】:

    ws.close()这样用就行了。

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

    【讨论】:

      【解决方案5】:

      如果您使用var client = net.createConnection() 创建套接字,您可以使用client.destroy() 销毁它。

      ws 应该是:

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

      【讨论】:

        猜你喜欢
        • 2022-11-18
        • 1970-01-01
        • 1970-01-01
        • 2020-07-04
        • 2019-01-08
        • 2019-12-11
        • 2021-10-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多