关闭连接后如何重新连接到websocket [重复]

Posted

技术标签:

【中文标题】关闭连接后如何重新连接到websocket [重复]【英文标题】:How to reconnect to websocket after close connection [duplicate] 【发布时间】:2012-11-27 15:34:04 【问题描述】:

我用这段代码(例如)构建我的 websocket 连接:

var socket = new WebSocket("ws://94.12.176.177:8080");

我关闭了与这个的连接:

socket.close();

但是我该如何重新建立连接呢?

我做了一些研究并尝试了几种方法。这个问题帮不了我:Socket.io reconnect on disconnect? 这是唯一接近我正在寻找的结果。

我想这样做的原因是允许用户暂时停止向网络发送数据,并在一段时间后重新发送。如果没有重新连接,用户必须刷新页面才能重新发送。这可能会导致一些数据丢失。谢谢。

【问题讨论】:

再做一个新的WebSocket。重新连接不存在的原因是因为它可能就像创建一个新连接一样。 Reconnection of client when the server reboots in WebSocket 的可能副本。 这是一种可能的解决方案:github.com/gdi2290/angular-websocket/issues/100 【参考方案1】:

当服务器关闭连接时,客户端不会尝试重新连接。也许有一些 JS 框架,但问题是,在这个答案的时候,被标记为普通的 Vanilla JS。

我有点沮丧,因为接受的、赞成的答案显然是错误的,而且我在找到正确的解决方案时花费了一些额外的时间。

这里是:Reconnection of Client when server reboots in WebSocket

【讨论】:

很抱歉让您失望了。 OP 链接到socket.io 问题,这一定是他使用的框架。该问题应标记为socket.io 感谢您的链接;它成功了。接受的答案没有意义,因为我正在使用没有框架的 websocket。 您指向的答案与@Jivings 建议的基本相同。除了这个没有提到socket.close实例方法。【参考方案2】:

我在这个页面上找到了一个很好的解决方案:sam-low.com

原始连接关闭后,您需要创建一个带有新事件侦听器的新 WebSocket 对象

function startWebsocket() 
  var ws = new WebSocket('ws://localhost:8080')

  ws.onmessage = function(e)
    console.log('websocket message event:', e)
  

  ws.onclose = function()
    // connection closed, discard old websocket and create a new one in 5s
    ws = null
    setTimeout(startWebsocket, 5000)
  


startWebsocket();

请注意,如果重新连接出现问题,新的 WebSocket 对象仍会收到另一个关闭事件,这意味着即使在技术上从未打开过 onclose() 也会执行。这就是为什么延迟 5 秒是明智的 - 没有它,您会发现自己创建和销毁数千个 websocket 连接的速度可能会破坏某些东西。

【讨论】:

对不起,这是优化的方式吗?【参考方案3】:

注意:该问题已标记为 socket.io,因此此答案专门针对 socket.io。 正如许多人指出的那样,这个答案不适用于 vanilla websockets,它在任何情况下都不会尝试重新连接。

Websockets 不会自动尝试重新连接。您必须重新创建套接字才能获得新连接。唯一的问题是您必须重新附加您的处理程序。

但实际上,websocket 旨在保持打开状态。

更好的方法是让服务器关闭连接。这样,websocket 将触发onclose 事件,但会继续尝试建立连接。当服务器再次监听时,连接将自动重新建立。

【讨论】:

客户端套接字尝试重新建立连接的行为-我猜这是socketio的事情? (不是基本的 websockets 东西?) @UpTheCreek 是的,我想是的。如果您调用 close(),普通 websockets 将不会尝试重新连接 我正在使用 WebSockets 和 TLS 的开源纯 AS3 实现,但我决定浏览器的实现会保持最新,所以我创建了一个 JS WebSocket 管理器,我的 AS3 WebSocket上课的电话。管理器构造具有唯一 ID 和回调的实例,将事件和套接字 ID 转发到 Flash 中的静态方法,然后查找相应的 AS3 实例并在其上调度事件。这允许我“重新连接();”无需重新附加事件处理程序,因为 AS3 WebSocket 只是在底层请求一个新的 JS WebSocket 和 ID。 当服务器关闭连接时,客户端不会尝试重新连接。可能有一些 JS 框架,但问题被标记为普通的 Vanilla JS。 普通的香草 js 没有自动重新连接是有充分理由的。当 websocket 服务器宕机时,谁愿意让他的代理受到攻击?花点时间实施适合您需求的重新连接策略。【参考方案4】:

完美的实现:

var socket;

const socketMessageListener = (event) => 
  console.log(event.data);
;

const socketOpenListener = (event) => 
  console.log('Connected');
  socket.send('hello');
;

const socketCloseListener = (event) => 
  if (socket) 
    console.error('Disconnected.');
  
  socket = new WebSocket('ws://localhost:8080');
  socket.addEventListener('open', socketOpenListener);
  socket.addEventListener('message', socketMessageListener);
  socket.addEventListener('close', socketCloseListener);
;

socketCloseListener();

测试它:

setTimeout(()=>
  socket.close();
,5000);

编辑:注意指数退避实现(在顶部评论的链接线程中:https://***.com/a/37038217/8805423),不在上面的代码中,但非常非常关键。

再次编辑:从primus 中查看back:https://www.npmjs.com/package/back,这是一个灵活的性感实现。

【讨论】:

我不喜欢您将其称为“完美实施”的方式。完美无瑕是为了什么?最好让其他人通过选票来判断。如何从关闭处理程序中创建套接字很聪明。也许这可能是介绍性的线,而不是。 @Pol 答案更简单更干净【参考方案5】:

function wsConnection(url)
    var ws = new WebSocket(url);
    var s = (l)=>console.log(l);
	ws.onopen = m=>s(" CONNECTED")
    ws.onmessage = m=>s(" RECEIVED: "+JSON.parse(m.data))
    ws.onerror = e=>s(" ERROR")
    ws.onclose = e=>
        s(" CONNECTION CLOSED");
        setTimeout((function() 
            var ws2 = new WebSocket(ws.url);
			ws2.onopen=ws.onopen;
            ws2.onmessage = ws.onmessage;
            ws2.onclose = ws.onclose;
            ws2.onerror = ws.onerror;
            ws = ws2
        
        ).bind(this), 5000)
    
    var f = m=>ws.send(JSON.stringify(m)) || "Sent: "+m;
    f.ping = ()=>ws.send(JSON.stringify("ping"));
    f.close = ()=>ws.close();
    return f


c=new wsConnection('wss://echo.websocket.org');
setTimeout(()=>c("Hello world...orld...orld..orld...d"),5000);
setTimeout(()=>c.close(),10000);
setTimeout(()=>c("I am still alive!"),20000);
<pre>
This code will create a websocket which will 
reconnect automatically after 5 seconds from disconnection.

An automatic disconnection is simulated after 10 seconds.

【讨论】:

以上是关于关闭连接后如何重新连接到websocket [重复]的主要内容,如果未能解决你的问题,请参考以下文章

关闭连接到 Mojo websocket 的 Mojo::IOLoop 重复事件

当python中的连接失败时如何重新连接到websocket

WebSocket 连接到 'ws:url' 失败:WebSocket 在连接建立之前关闭

WebSocket 连接到 'ws://localhost:4444/subscriptions' 失败:WebSocket 在连接建立之前关闭

如何正确关闭 websocket

不断重新连接到 websocket / 会话 ID 未知 / Etherpad