简体   繁体   English

如何终止 WebSocket 连接?

[英]How to terminate a WebSocket connection?

Is it possible to terminate a websocket connection from server without closing the entire server?是否可以在不关闭整个服务器的情况下终止来自服务器的 websocket 连接? If it is then, how can I achieve it?如果是这样,我怎样才能实现它?

Note: I'm using NodeJS as back-end and 'ws' websocket module.注意:我使用 NodeJS 作为后端和 'ws' websocket 模块。

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.因此,由于文档中有关ws.close()ws.terminate()某种遗漏,我认为提供的答案中的解决方案在某些情况下不会正常关闭套接字,从而使它们挂在事件循环中。

Compare the next two methods of ws package:比较下ws包的两种方法:

  • ws.close() : 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.初始化关闭握手,向对等方发送关闭帧并等待从对等方接收关闭帧,然后发送 FIN 数据包以尝试执行干净的套接字关闭。 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:但是,有一个closeTimeout只会在最坏的情况下销毁套接字,并且它可能会将套接字保留额外的 30 秒,从而阻止自定义超时的正常退出:

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

Forcibly destroys the socket without closing frames or fin packets exchange, and does it instantly, without any timeout.强行销毁套接字而不关闭帧或 fin 数据包交换,并立即执行,没有任何超时。

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):如果您可以让自己等待一段时间(但不是 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);

Important: proper execution of close() method will emit 1000 close code for close event, while terminate() will signal abnormal close with 1006 ( MDN WebSocket Close event ).重要提示: close()方法的正确执行将为close事件发出1000关闭代码,而terminate()将用1006发出异常关闭信号( MDN WebSocket 关闭事件)。

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.如果您想特别寻找一个,您也可以过滤wss.clients If you want to kick a client as part of the connection logic (ie 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.根据ws 文档,您需要调用websocket.close()来终止连接。

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

Jus use ws.close() in this way.就是这样使用ws.close()

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.如果您使用var client = net.createConnection()创建套接字,您可以使用client.destroy()销毁它。

With ws it should be:使用ws应该是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM