#javascript #node.js #websocket #ws
Вопрос:
Я использую следующую логику, чтобы проверить, подключен ли клиент к websocket или нет: клиент продолжает отправлять сообщения с интервалом на сервер. У сервера есть тайм — аут, который запускает событие при завершении. Как только клиент связывается с сервером, тайм-аут сервера сбрасывается. Это прекрасно работает, когда подключен один клиент. Но логика нарушается на нескольких клиентах. Как я могу это исправить? Как только 2-й клиент подключается, Сервер сообщает, что клиент 1 отключился и ничего не печатает, когда отключается один из 2.
Это моя серверная логика:
const WebSocket = require("ws"); const express = require("express"); const app = express(); const server = require("http").createServer(app); const url = require('url'); const PORT = process.env.PORT || 3000; const wss = new WebSocket.Server({ server: server }); app.get("/", (req, res) =gt; res.send("Temst.")); var tm; function ping(client) { tm = setTimeout(function () { console.log(`[-] ${client} Disconnected`); wss.emit("customClose", client); }, 5000); } function pong(client) { clearInterval(tm); // console.log("[!] Cleared timeout"); ping(client); } wss.on("connection", function connection(ws, req) { var queryData = url.parse(req.url,true).query; ping(queryData.id); console.log(`[ ] ${req.socket.remoteAddress} Connected`); wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { message = { type: "alert", msg: `${queryData.id} has Connected.`, }; client.send(JSON.stringify(message), { binary: false }); } }); ws.on("message", function incoming(message) { if (message == "__ping__") { console.log(`[!] Ping Receieved from ${req.socket.remoteAddress}`); pong(queryData.id); } else { `[!] Message Receieved from ${req.socket.remoteAddress}`; wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { client.send(msg, { binary: false }); } }); } }); }); wss.addListener("customClose", function (m) { wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { message = { type: "alert", msg: `${m} has Disconnected.`, }; client.send(JSON.stringify(message), { binary: false }); } }); }); server.listen(PORT, () =gt; console.log("Listening on port 3000"));
Ответ №1:
Я думаю, что решил эту проблему. Посмотрев документы пакета ws, я попробовал пинговать на стороне сервера, а не на стороне клиента. На данный момент он работает для нескольких пользователей. Будет обновляться, если возникнут какие-либо проблемы.
const WebSocket = require("ws"); const express = require("express"); const app = express(); const server = require("http").createServer(app); const url = require("url"); const PORT = process.env.PORT || 3000; const wss = new WebSocket.Server({ server: server }); app.get("/", (req, res) =gt; res.send("Temst.")); var myClients = []; wss.on("connection", function connection(ws, req) { var queryData = url.parse(req.url, true).query; myClients.push({ id: queryData.id, wsoc: ws, isAlive: true, }); console.log(`[ ] ${req.socket.remoteAddress} Connected`); wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { message = { type: "alert", msg: `${queryData.id} has Connected.`, }; client.send(JSON.stringify(message), { binary: false }); } }); ws.on("pong", () =gt; { let x = myClients.find((o) =gt; o.wsoc === ws); x.isAlive = true; }); ws.on("message", function incoming(message) { console.log(`[!] Message Receieved from ${req.socket.remoteAddress}`); msg = JSON.parse(message); console.log(queryData); msg = { ...msg, time: new Date().toISOString() }; wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { client.send(JSON.stringify(msg), { binary: false }); } }); }); }); wss.addListener("customClose", function (m) { wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { message = { type: "alert", msg: `${m} has Disconnected.`, }; client.send(JSON.stringify(message), { binary: false }); } }); }); const interval = setInterval(function ping() { myClients.forEach((clnt, index) =gt; { if (clnt.isAlive === false) { console.log("[-]", clnt.id, "has Disconnected."); wss.emit("customClose", clnt.id); clnt.wsoc.terminate(); myClients.splice(index, 1); } clnt.isAlive = false; clnt.wsoc.ping(); }); }, 5000); server.listen(PORT, () =gt; console.log("Listening on port 3000"));