24

在 Node.js 中,我使用websockets/ws进行 WebSocket 连接。下面是客户端的代码。假设我们要连接的服务器套接字关闭了一分钟。close 事件将触发,但是当服务器上的套接字出现故障或错误时,重新连接到套接字的最佳方法是什么?

var ws = new WebSocket('ws://localhost');

ws.on('open', function() {
    console.log('socket open');
});
ws.on('error', function() {
    console.log('socket error');
    // how do I reconnect to the ws after x minutes here?
});
ws.on('close', function() {
    console.log('socket close');
    // how do I reconnect to the ws after x minutes here?
});
4

6 回答 6

37

尝试这个:

var reconnectInterval = x * 1000 * 60;
var ws;
var connect = function(){
    ws = new WebSocket('ws://localhost');
    ws.on('open', function() {
        console.log('socket open');
    });
    ws.on('error', function() {
        console.log('socket error');
    });
    ws.on('close', function() {
        console.log('socket close');
        setTimeout(connect, reconnectInterval);
    });
};
connect();

您无需包装即可使用原始实现。

于 2014-10-04T16:51:10.200 回答
12

我已经成功使用了https://github.com/joewalnes/reconnecting-websocket/blob/master/reconnecting-websocket.js

你应该能够做到:

ws = new ReconnectingWebSocket('ws://....');
ws.reconnectInterval = 60000; // try to reconnect after 10 seconds
于 2013-10-30T19:30:00.663 回答
12

2018 年 1 月更新

重新连接到断开连接的 Web 套接字并非易事,最好委托给库。目前为此目的最小且维护最积极的库是reconnecting-websocket,它从另一个答案中淘汰了 joewalnes 的库。特别是对于 Node.js,您需要传递一个构造函数,例如 WebSocket:

import WebSocket from 'ws';
import ReconnectingWebSocket from 'reconnecting-websocket';
const ws = new ReconnectingWebSocket('wss://some-feed.com', [], {
  constructor: WebSocket,
  connectionTimeout: ...,  // in milliseconds
  reconnectInterval: ...,
});
于 2018-01-12T00:30:46.050 回答
5

如果套接字关闭或服务器上发生任何错误,则使用 async-await 客户端将永远尝试每 5 秒自动连接一次

var ws = require('ws')
var openedSocket = null
var timeInterval = 5000
var port = 3000
var url = `ws://localhost:${port}`

function connect() {
  var client = new ws(url)
  return new Promise((resolve, reject) => {
    console.log('client try to connect...')

    client.on('open', () => {
      console.log('WEBSOCKET_OPEN: client connected to server at port %s', port)
      openedSocket = true
      resolve(openedSocket)
    })

    client.on('message', (data) => {
      console.log(data.toString())
    })

    client.on('close', (err) => {
      console.log('WEBSOCKET_CLOSE: connection closed %o', err)
      openedSocket = false
      reject(err)
    })

    client.on('error', (err) => {
      console.log('WEBSOCKET_ERROR: Error', new Error(err.message))
      openedSocket = false
      reject(err)
    })
  })
}

async function reconnect() {
  try {
    await connect()
  } catch (err) {
    console.log('WEBSOCKET_RECONNECT: Error', new Error(err).message)
  }
}

reconnect()

// repeat every 5 seconds
setInterval(() => {
  if (!openedSocket) {
    reconnect()
  }
}, timeInterval)
于 2021-04-14T23:42:25.037 回答
0

您应该考虑迁移到socket.io.

  1. 它具有内置的自动重新连接功能。而且您无需为此做任何事情。默认情况下已启用它。
  2. 令人惊讶的是,它与旧版浏览器兼容,甚至是不支持本机 websocket 的浏览器。

两者的代码非常相似,但socket.io可能只是更短一点。例如,对于我们用来编写类似这样的服务器代码:

const WebSocketServer = require('websocket').server
const ws = new WebSocketServer({ httpServer });
ws.on('request', (request) => onConnection(request));

function onConnectionRequest(request) {
  const connection = request.accept(null, request.origin);
  if (!connection) return;
  connection.on('message', (msg) => onMessageReceived(msg));
  connection.on('close', () => onConnectionClosed());
}

function onMessage(message) {
  if (message.type === 'utf8') {
    const data = message.utf8Data;
    const request = JSON.parse(data);
    // todo use request
  }
}

Socket.io 代码非常相似,只是更短一些。

const io = require('socket.io')(httpServer);
io.on('connection', (socket) => onConnection(socket));

function onConnection(socket) {
  socket.on('message', (msg) => onMessage(msg));
  socket.on('disconnect', (reason) => onDisconnect(reason));
}

function onMessage(request) {
  // todo use request
}

但是,请记住,您还必须重写客户端代码。例如对于 Angular,我使用ngx-socket-io插件,它极大地简化了代码。

于 2019-01-13T22:12:16.610 回答
0

在检查了@Mohamed Farouk 的答案后,我相信使用承诺来表示连接状态是有好处的。这是一个示例,该示例从该答案中提取了一些内容,并从我的原始内容中提取了一些内容:

const address = "ws://localhost";
const reconnectInterval = x * 1000 * 60;
const ws = {};
const establishSocket = address => new Promise((resolve, reject)=>{
  const s = new WebSocket(address);
  s.on("open", ()=>{
    delete ws.reason;
    ws.socket = s;
    console.log('socket open');
  });
  s.on("error", ()=>console.log('socket error'));
  s.on("close", reject);
}).catch(async (reason)=>{
  ws.socket = null;
  ws.reason = reason;
  console.log('socket close');
  await new Promise(resolve=>setTimeout(resolve, reconnectInterval));
  establishSocket(address);
});
establishSocket(address);

我没有断言哪种方法更好——我只是认为这是一个有趣的解决方案。

于 2021-11-25T13:12:42.877 回答