WebSocket:死后如何自动重新连接
Posted
技术标签:
【中文标题】WebSocket:死后如何自动重新连接【英文标题】:WebSocket: How to automatically reconnect after it dies 【发布时间】:2014-03-16 01:04:44 【问题描述】:var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function ()
ws.send(JSON.stringify(
.... some message the I must send when I connect ....
));
;
ws.onmessage = function (e)
console.log('Got a message')
console.log(e.data);
;
ws.onclose = function(e)
console.log('socket closed try again');
ws.onerror = function(err)
console.error(err)
;
当我第一次连接到socket时,我必须先向服务器发送一条消息来验证自己并订阅频道。
我遇到的问题是,有时套接字服务器不可靠,这会触发 'ws'
对象的 onerror
和 onclose
事件。
问题:有什么好的设计模式可以让我在套接字关闭或遇到错误时等待 10 秒,然后重新连接到套接字服务器(并将初始消息重新发送到服务器)
【问题讨论】:
Reconnection of Client when server reboots in WebSocket的可能重复 【参考方案1】:这就是我最终的结果。它适用于我的目的。
function connect()
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function()
// subscribe to some channels
ws.send(JSON.stringify(
//.... some message the I must send when I connect ....
));
;
ws.onmessage = function(e)
console.log('Message:', e.data);
;
ws.onclose = function(e)
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
setTimeout(function()
connect();
, 1000);
;
ws.onerror = function(err)
console.error('Socket encountered error: ', err.message, 'Closing socket');
ws.close();
;
connect();
【讨论】:
是否重新连接到它之前连接的同一个 websocket?因为我使用 websocket id 来发送消息,但是如果它有新的 websocket id 就很难将消息发送到特定系统。 @AlexanderDunaev,添加超时主要是为了避免在服务器不可用时过于激进的重新连接,即网络中断或本地调试服务器关闭。但总的来说,我认为立即重新连接,然后以指数级增长的重新连接等待时间比固定的 1 秒等待稍好一些。 连接关闭时 websocket 实例会发生什么。是垃圾回收,还是浏览器堆积了一堆未使用的对象? setTimeout(connect,1000) 是一种更简洁、更节省资源的延迟重新连接的方法。还可以考虑使用 setTimeout (connect ,Math.min(10000,timeout+=timeout)),在第一次连接之前和每次成功连接之后将超时重置为 250。这样,连接期间的错误情况会增加一个退避,但如果是一次性错误情况,则会快速重新连接 - 250,500,1000,2000,4000,8000,10000,10000 毫秒延迟不那么激进,但比 1000,1000 响应更快,1000 毫秒 我在这段代码中看到的问题是,如果连接关闭,我们再次尝试打开连接,但失败了,那么我们将永远不会重试。【参考方案2】:这对我有用 setInterval
,因为客户端连接可能会丢失。
ngOnInit(): void
if (window.location.protocol.includes('https'))
this.protocol = 'wss';
this.listenChanges();
listenChanges(): void
this.socket = new WebSocket(`$this.protocol://$window.location.host/v1.0/your/url`);
this.socket.onmessage = (event): void =>
// your subscription stuff
this.store.dispatch(someAction);
;
this.socket.onerror = (): void =>
this.socket.close();
;
this.socket.onopen = (): void =>
clearInterval(this.timerId);
this.socket.onclose = (): void =>
this.timerId = setInterval(() =>
this.listenChanges();
, 10000);
;
;
当套接字打开时不要忘记调用clearInterval
。
【讨论】:
【参考方案3】:这不是一个明确的反应问题,但这是一个反应风格的答案:
TLDR:您可以使用setInterval
定期检查websocket连接状态,如果连接关闭则尝试重新连接。 https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
class TestComponent extends React.Component
constructor(props)
super(props);
this.state = ;
this.connect = this.connect.bind(this);
componentDidMount()
this.interval = setInterval(this.connect, 1000);
componentWillUnmount()
if (this.ws) this.ws.close();
if (this.interval) clearInterval(this.interval);
connect()
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
if (this.ws === undefined || (this.ws && this.ws.readyState === 3))
this.ws = new WebSocket(`ws://localhost:8080`);
this.ws.onmessage = (e) =>
console.log(JSON.parse(e.data));
;
render()
return <div>Hey!</div>;
【讨论】:
【参考方案4】:如果套接字关闭或服务器上发生任何错误,则使用 async-await 客户端将永远尝试每 5 秒自动连接一次 看看my answer
【讨论】:
【参考方案5】:我发现这个包https://github.com/pladaria/reconnecting-websocket可以解决Websocket连接的重连问题。它有一个可配置选项列表,其中之一是reconnectionDelayGrowFactor
,它决定了重新连接延迟增长的速度。
【讨论】:
【参考方案6】:更新答案:
最后,(如果您不使用 java)我发现您最好实现自己的“ping/pong”策略。 (如果你用的是java,请看一下ping/pong“动作类型”,我记不太清楚了……)
-
客户端每 5 秒向服务器发送一次“ping”。
一旦收到“ping”,服务器应向客户端回显“pong”。
如果在 5 秒内没有收到“pong”,客户端应该重新连接服务器。
不要依赖任何第三方库。
警告:请勿使用这些工具:(原因:它们不可靠且不稳定,并且工作方式非常有限。)
-
检查网络是否可用:https://github.com/hubspot/offline
重新连接:https://github.com/joewalnes/reconnecting-websocket
【讨论】:
github 库github.com/joewalnes/reconnecting-websocket 实际上作为new WebSocket()
的一个简单连接的简单插件。我知道这个答案一般来说有点离题,但为了简单起见,在这里使用提到的 javascript 库确实有效。
是的,你是对的!不要使用那 2 个 github 存储库。
为什么我们不应该使用它们?第二个看起来很有用。
你应该实施你的乒乓策略。不要相信打开/关闭事件。
请注意,在我撰写本文时,ReconnectingWebSocket 不支持 'binaryType' 选项:它似乎有 50% 的时间退回到 'blob',并且缩小的 JS 不包含以下功能全部。所以我就自己动手了。【参考方案7】:
如果需要,您可以使用small library - ReconnectingWebSocket
在您的脚本标签中添加 reconnecting-websocket.js 和
它是 API 兼容的,所以当你有:
var ws = new WebSocket('ws://....');
您可以替换为:
var ws = new ReconnectingWebSocket('ws://....');
【讨论】:
以上是关于WebSocket:死后如何自动重新连接的主要内容,如果未能解决你的问题,请参考以下文章
tomcat 7.0支持的最大活动websocket连接数是多少
socket 用disconnect 断开,再重新连接怎么搞
websocket._exceptions.WebSocketProxyException:通过代理连接失败状态:503