在Node.js我正在使用websockets/ws进行WebSocket连接。下面是客户端的代码。假设我们要连接的服务器套接字关闭了一分钟。关闭事件将触发,但是每当服务器上的套接字关闭或出错时,重新连接到套接字的最佳方法是什么?
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?
});
试试这个:
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();
您可以使用原始实现而无需包装它。
我已经成功地使用了 https://github.com/joewalnes/reconnecting-websocket/blob/master/reconnecting-websocket.js。
您应该能够执行以下操作:
ws = new ReconnectingWebSocket('ws://....');
ws.reconnectInterval = 60000; // try to reconnect after 10 seconds
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: ...,
});
使用 async-await 如果套接字关闭或服务器上发生任何错误,客户端将尝试每 5 秒永久自动连接一次
const ws = require('ws')
let openedSocketFlag = null
const timeInterval = 5000
const port = 3000
const url = `ws://localhost:${port}`
function connect() {
const 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)
openedSocketFlag = true
resolve(openedSocketFlag)
})
client.on('message', (data) => {
console.log(data.toString())
})
client.on('close', (err) => {
console.log('WEBSOCKET_CLOSE: connection closed %o', err)
openedSocketFlag = false
reject(err)
})
client.on('error', (err) => {
console.log('WEBSOCKET_ERROR: Error', new Error(err.message))
openedSocketFlag = 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 (!openedSocketFlag) {
reconnect()
}
}, timeInterval)
在检查了法鲁克@Mohamed答案后,我认为用承诺来表示是有好处的连接的状态。这里有一个例子,从这个答案中汲取了一点,还有一点从我的原文:
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);
我没有断言哪种方法更好 - 我只是认为这是一个有趣的解决方案。
您应该考虑迁移到 socket.io
。
- 它具有内置的自动重新连接功能。而且您不必为此做任何事情。默认情况下,它已启用。
- 令人惊讶的是,它与较旧的浏览器兼容,甚至是不支持本机 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
插件,这极大地简化了代码。
我在客户端中使用了"websocket"反应/nextjs,这是特定包的URL:https://www.npmjs.com/package/websocket https://github.com/theturtle32/WebSocket-Node
并且当服务器重新启动时,我正在使用"重新连接-websocket"包将客户端Websocket重新连接到服务器(即Django通道)。这是官方软件包网址:
https://www.npmjs.com/package/reconnecting-websocket
这是一个简单的用法示例:
import { w3cwebsocket as W3CWebSocket } from "websocket";
import ReconnectingWebSocket from 'reconnecting-websocket';
//inside react component - nextjs page :
const options = {
WebSocket: W3CWebSocket, // custom WebSocket constructor
connectionTimeout: 1000,
maxRetries: 10,
};
const isServerSide = typeof window === "undefined";
let client
if(!isServerSide) {
client = new ReconnectingWebSocket(`ws://127.0.0.1:8000/ws/`,[], options);
client.binaryType = "arraybuffer";
}
useEffect(() => {
client.onopen = () => {
console.log('WebSocket Client Connected');
};
client.onerror = (error) => {
console.log("Connection Error: " , error);
};
client.onclose = (close) => {
console.log('echo-protocol Client Closed', close);
};
}, [])
这只是示例,并根据您的情况/要求进行更改.
我希望这有帮助