在浏览器选项卡之间共享WebSocket?

47

我们希望每个浏览器只有一个套接字,而不是每个选项卡都有一个。我们该如何实现?我阅读了关于共享Web Workers的文章,这是很有前途的。如果有参考资料就更好了。不幸的是,据我所知,Mozilla或Internet Explorer尚未实现共享Web Workers。那么在这种情况下应该怎么做?我们正在服务器端使用Node.js。


Web Workers自Firefox 3.6版本以来就可以使用。唯独Internet Explorer不支持(当然这是意料之中的)。 - Rob
1
我不确定现在是否可能。你有查看Socket.io文档/常见问题解答吗?无论如何,我找到了这个关于共享工作者的链接http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#shared-workers-introduction,听起来很有前途,但还没有实现:( 希望这可以帮助 :) - pomeh
我正在使用socket.io,但并没有找到可以解决上述问题的内容。 - singhsumit
9个回答

12
在看到这个问题后,我最终实现了共享套接字并在几天前将其添加到我的库中。它似乎在大多数浏览器中都能工作,甚至包括IE6,但不适用于Opera。对于Opera,您可以使用定期检查而不是unload事件。
请参阅相关问题https://github.com/flowersinthesand/portal/issues/21 ###留下cookie
  1. 设置cookie以通知有共享套接字。
  2. 当套接字关闭时,删除该cookie以通知没有共享套接字。
请参阅https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L629-L650 ###共享和使用共享套接字
  1. 使用 storage 事件和 localStorage - 当设置或删除值时,localStorage 会触发 storage 事件。
  2. 检查是否支持 StorageEvent 和 localStorage。
  3. 添加 storage 事件处理程序,通过键过滤事件。我使用 socket 的 url 作为键。
  4. 添加 socket 的关闭事件,以删除存储属性。
  5. 要发送信号,请将先前的键数据设置到 storage 中。

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

使用 shared:https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L851-L893

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

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

使用分享的内容:https://github.com/flowersinthesand/portal/blob/7c2ce4bb61d05d80580e6cde6c94a78238a67345/jquery.socket.js#L894-L929

注意

  1. 在上述实现中,信令是广播的,因此数据应指示目标。我使用了目标属性,p表示父级,c表示子级。
  2. 我使用了额外的变量来共享套接字:opened-共享套接字是否打开,children-共享者列表。代码和注释将帮助您了解详细信息。

我希望我的回答对您有所帮助。


1
“Portal” 项目现已过时,并已迁移到 Cettia,目前仅处于 alpha 版本。 - Dmitry Gonchar

8

似乎不能免费使用。 - Sebastian Nielsen

8

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


6
我正在使用localStorage作为共享通信渠道,以便使用与EventEmitters完全相同的接口在标签之间发送数据。结合领导者选举算法决定哪个标签将连接到服务器,我从所有追随者标签中将所有套接字事件转发到领导者标签,反之亦然。最后,领导者标签将所有事件转发到服务器,并将所有接收到的事件广播给所有其他客户端。以下是代码:

3

我仍在为我即将开始构建的设计理论化,但我考虑将以下内容进行组合:

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

我的理论是在每个选项卡中每次页面加载时在javascript中创建一个套接字引擎,但如果已经有一个已建立的连接,则会关闭。

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

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

一旦运行起来,它将通过将我想要在选项卡之间共享的数据转换为JSON blob,然后在其他选项卡中接收时将其转换回对象,向其他选项卡提供交叉窗口消息。无论哪个选项卡获得连接,都将处理与套接字服务器的所有传入/传出消息。然后它将通过跨窗口消息与其他选项卡接收/发送。理论上,这也应该适用于iframe和弹出窗口。

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

我的梦想情景是,如果用户A正在查看票1000,而用户B更新了票1000,我希望用户A的票刷新,如果用户A在刷新之前进行了更改,我希望给他们一个数据迁移弹出窗口,以防止删除用户B的更改。

--用户B在您编辑此记录时进行了冲突更改 “UserB:FirstName-> Bob”[接受] “UserA:FirstName-> Robert”[保留]


3

1

请查看https://github.com/nodeca/tabex

您需要为跨标签页通信添加额外的层。Tabex提供了Faye使用示例。其他WebSocket传输(如socket.io等)也可以以类似的方式使用。


1

目前 socket.io 实现的方式似乎没有解决方案。请在 this 视频中查看 Guillermo Rauch,在第五部分也将其视为挑战。


0

实际上,避免这些问题有些困难,例如:在网络不稳定时断开连接。毕竟,网页最初的目的是交换不同的文本文件(如RFC文件),只需要短暂、低成本和不稳定的传输方式(我认为这才是设置HTTP协议的最初目的)

当然,为了解决这个问题,我建议您像上面说的那样使用共享工作者或使用LocalStorage存储共享和公共部分的信息。

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

希望它能真正地帮到您!(其实还没有)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接