跨浏览器选项卡共享 websocket?

Posted

技术标签:

【中文标题】跨浏览器选项卡共享 websocket?【英文标题】:Sharing websocket across browser tabs? 【发布时间】:2012-03-22 05:32:57 【问题描述】:

我们希望每个浏览器有一个套接字,而不是浏览器中的每个选项卡一个。我们怎样才能实现它?我读到了很有希望的共享网络工作者。对此的参考也值得赞赏。不幸的是,据我所知,Mozilla 或 Internet Explorer 尚未实现共享网络工作者。那么在这种情况下该怎么办呢?我们正在服务器端开发 node.js。

【问题讨论】:

Web Workers 从 3.6 版开始就在 Firefox 中工作。只有 Internet Explorer 无法使用此功能(当然,正如预期的那样)。 我不知道现在是否可行。您查看过 Socket.io 文档/常见问题解答吗?无论如何,我发现了这个关于共享工作者的whatwg.org/specs/web-apps/current-work/multipage/…,听起来很有希望,但还没有实现:(希望有帮助:) 我正在使用socket.io,但找不到可以解决上述问题的任何东西。 【参考方案1】:

看到这个问题后,我终于实现了共享套接字,并在几天前添加到我的库中。它似乎适用于大多数浏览器,甚至包括 IE6,但 Opera 除外。对于 Opera,您可以使用常规检查而不是卸载事件。

在https://github.com/flowersinthesand/portal/issues/21查看相关问题

留下一个 cookie

    设置 cookie 以通知存在共享套接字。 当套接字关闭时,删除该 cookie 以通知没有共享套接字。

见,https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L629-650

共享和使用共享套接字

    使用存储事件和 localStorage - localStorage 在设置和删除值时触发存储事件。
      检查是否支持 StorageEvent 和 localStorage。 添加按键过滤事件的存储事件处理程序。我用socket的url作为key 添加删除存储属性的套接字关闭事件 要发出信号,请使用前一个键将数据设置为存储

分享:https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L531-568

使用共享:https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L851-893

    使用 window.open 方法 - 如果我们知道共享窗口的名称,我们可以获取该窗口的引用并访问其属性。
      每个浏览器都支持 window.open 方法,但某些浏览器(例如 Chrome)禁止访问返回的窗口的属性。 获取或创建 name 属性为 key 的 iframe。我使用了socket的url,但是注意IE不允许在iframe标签的name属性中使用非单词字符。 Iframe 的 contentWindow 是共享窗口引用。设置回调变量来存储每个窗口的监听器。 要发出信号,只需使用数据调用回调。请注意,IE 8 及更低版本只允许将字符串传递给其他窗口的函数,并且共享窗口可能会被破坏。

分享:https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L571-605

使用共享:https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L894-929

注意

    在上面的实现中,信令是广播的,所以数据应该指明目标。我使用了目标属性,p 代表父项,c 代表子项。 我使用附加变量来共享套接字:opened - 共享套接字是否打开,children - 共享者列表。代码和 cmets 将帮助您了解详细信息。

希望我的回答对你有帮助。

【讨论】:

“Portal”项目现已过时,已移至 Cettia,目前仅处于 alpha 阶段【参考方案2】:

在某些情况下,我使用 localStorage 对象在选项卡之间进行通信。 localStorage 对象有一个事件系统来告诉另一个相同来源的选项卡或窗口某些数据已更改(http://www.codediesel.com/javascript/sharing-messages-and-data-across-windows-using-localstorage/)。这个想法是,让带有套接字的选项卡将时间戳和接收到的数据写入本地存储。如果时间戳太旧 - 可能是因为带有套接字的选项卡已关闭 - 另一个选项卡可以启动套接字连接并更新数据和时间戳。

【讨论】:

【参考方案3】:

2016 年的答案必须是 Shared Web Workers,如本博客所述:

https://blog.pusher.com/reduce-websocket-connections-with-shared-workers/

【讨论】:

【参考方案4】:

我使用 localStorage 作为共享通信通道,以便使用与 EventEmitters 相同的接口在选项卡之间发送数据。再加上决定哪个选项卡将连接到服务器的领导者选举算法,我将所有套接字事件从所有跟随者选项卡中继到领导者选项卡,反之亦然。最后,leader 选项卡将所有事件转发到服务器,并将所有接收到的事件广播给所有其他客户端。代码如下:

https://github.com/majestic3/athena-online-judge/blob/master/source/client/core/itc.js https://github.com/majestic3/athena-online-judge/blob/master/source/client/core/socket.js

【讨论】:

【参考方案5】:

远非理想,但您可以使用 flash 本地连接来设置一个 websocket 连接,然后在选项卡和多个浏览器之间共享它。

更多信息请参见http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/LocalConnection.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6。

【讨论】:

【参考方案6】:

对于我准备开始构建的设计,我仍在对此进行理论分析。但是,我正在考虑合并

-WebSockets -本地存储 和 - 跨窗口消息传递

我的理论是在 javascript 中创建一个套接字引擎,该引擎在每个选项卡中的每个页面加载时运行,但如果已经建立了连接,它将关闭。

在第一次访问该站点时,我会让它创建一个 GUID 并将其存储在本地存储中,该 GUID 将唯一标识用户浏览器/登录到他们的 PC。

当套接字服务器接受连接时,它将具有该 guid,并且该 guid 的任何新请求都将返回“999 连接已建立”或类似的内容。

一旦运行,它将通过将我想要跨选项卡共享的数据转换为 JSON blob,然后在其他选项卡中接收到时将其转换回对象,从而为其他选项卡提供跨窗口消息传递。因此,无论哪个选项卡获取连接,都将使用套接字服务器处理所有传入/传出消息。然后它将通过跨窗口消息传递与其他选项卡一起接收/传输。从理论上讲,这也应该适用于 Iframe 和弹出窗口。

整个系统将推动加载表单的自动数据刷新,用于我们正在构建的类似 CRM 的系统以及实时聊天系统和票务板。

我的梦想场景是,如果用户 A 正在盯着工单 1000 并且用户 B 更新工单 1000,我希望用户 A 的工单刷新,如果用户 A 在刷新之前进行了更改,我想给他们一个数据迁移弹出窗口防止吹走用户 B 的更改

--用户 B 在您编辑此记录时进行了冲突更改 “用户B:名字->鲍勃”[Take] "UserA: FirstName -> Robert" [保持]

【讨论】:

【参考方案7】:

不要认为现在实现socket.io的方式似乎没有解决方案。在thisvideo 中查看 Guillermo Rauch,第五部分。他也认为这是一个挑战。

【讨论】:

【参考方案8】:

见https://github.com/nodeca/tabex

您需要额外的层来进行跨表通信。 Tabex 有 Faye 使用的示例。其他 websocket 传输(socket.io 等)可以类似的方式使用。

【讨论】:

【参考方案9】:

其实有些问题是很难避免的,比如:网络不稳定就掉线。毕竟页面最初是为了交换不同的文本文档(比如RFC文档),只需要一个简短的,低成本且不稳定的传输方式(我认为建立HTTP协议的最初目的)

当然,要解决这个问题,我建议你像上面说的那样使用shared worker,或者将shared和public部分的信息存储在LocalStorage

这里是LocalStorage基本用法介绍的链接

希望它真的希望你!(实际上还没有)

【讨论】:

以上是关于跨浏览器选项卡共享 websocket?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Vue.js 跨浏览器选项卡的反应式 localStorage 对象

如何解决IE浏览器跨域问题

Blazor Server 如何跨多个选项卡和刷新保存数据

怎么设置chrome浏览器可以跨域

遇上浏览器跨域问题怎么办?

WebSocket凭什么可以跨域?