m87*_*m87 12 javascript node.js
是否可以在不关闭整个服务器的情况下终止来自服务器的websocket连接?如果是的话,我该如何实现呢?
注意:我使用NodeJS作为后端和'ws'websocket模块.
Dam*_*nic 20
所以,因为文档中某种遗漏的关于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.
Run Code Online (Sandbox Code Playgroud)
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();
}
});
});
Run Code Online (Sandbox Code Playgroud)
如果你可以让自己等一会儿(但不是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);
Run Code Online (Sandbox Code Playgroud)
重要:正确执行close()方法将为事件发出1000紧密代码close,同时terminate()将发出异常关闭信号1006(MDN WebSocket Close事件).
Mei*_*hes 12
如果要在不关闭服务器的情况下启动所有客户端,可以执行以下操作:
for(const client of wss.clients)
{
client.close();
}
Run Code Online (Sandbox Code Playgroud)
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
});
Run Code Online (Sandbox Code Playgroud)
和一个基本的客户
"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");
};
Run Code Online (Sandbox Code Playgroud)
你会得到:
d:/example/node client
opened
something
closed
Run Code Online (Sandbox Code Playgroud)
根据ws文档,您需要调用websocket.close()来终止连接。
let server = new WebSocketServer(options);
server.on('connection', ws => {
ws.close(); //terminate this connection
});
Run Code Online (Sandbox Code Playgroud)