Websocket обнаруживает сбой отключения клиента

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