Web跨浏览器进程通信(Web跨域)
发布时间:2024-05-02 16:20:02
在之前一篇文章里尝试了跨浏览器的数据共享,最后提到使用LocalConnection还可以实现跨浏览器消息交互的可行性。
花了两个晚上简略的研究了下,LocalConnection的单向通信非常的简单,不过要实现多个终端交互,必须自己实现一套消息机制,见智见仁了。
为了简单演示,本例使用了基于广播的观察者模式:每个终端可以订阅自己感兴趣的主题,也可以向广播发送消息,通知其他感兴趣的终端。
Demo: http://www.etherdream.com/FunnyScript/WebIPC/ (多开几个浏览器页面小窗口,即可测试)
比较遗憾的是最新版的Chrome浏览器仍然无法和其他浏览器进程交互:(
如果没有错误发生,应该就是如下的效果:
在任何一个页面上的操作,都会立即同步到其他页面里,只要Observe了感兴趣的主题。
为什么要使用观察者模式呢?因为跨进程的通信是比较耗资源的,所以不感兴趣的消息可以直接不订阅,而不是收到再放弃。
LocalConnection是为单一的通信设计的,虽然使用很简单,但可用的接口少之又少。想直接用它来广播事件,或者消息路由,门都没有。
因此底层的消息发送上没有太多可选余地,只能简单的点对点发送。我们必须创建多个LocalConnection,来实现消息的汇聚和分发。
LocalConnection真正能用的只有两个方法:
connect(name)—— 创建管道(每个LocalConnection只能创建一个管道,每个管道名只能有一个)
send(name, ...)—— 向管道发送数据
如果只有两个终端通信,那么一切都是那么简单。。。
只需简单的将消息发送给对方即可。
不过有多个终端情况就大不相同了。由于我们是本地进程间通信,并没有第三方服务器主持,加上LocalConnection只能点对点的发送消息。意味着每次广播都要给其他所有的终端都发送一次,这样复杂度就大大增加了。
为了简化结构,我们模拟一个LocalConnection作为Host,在第一次启动时运行。其余的作为Client,每次广播消息都提交给Host,由它来调度。
Host维护着一个回调列表。当Client对某个主题(subject)感兴趣时,可以发送<主题ID,自己的管道名>给Host来订阅。于是Host就把此Client的管道名添加到该主题的回调列表里。以后若有该主题的消息,即可根据回调列表通知订阅的Client。
为了能让Host和Client通信更简单,这里使用channel+ID的命名规则,来创建管道名。
Host的ID为空,于是Client发送数据只需send(channel)即可;
Client的ID从1~100,选一个没用被占用的作为管道名。Host回调时只需send(channel+id)就能通知对应的Client。
然而,这个Host服务仅仅是假象的。我们根本没法在页面之外运行一个第三方服务,一切只能在页面中实现!于是我们把第一次启动的页面作为Host。当这个页面关闭时,我们再通知第二个页面创建Host,以此类推。。。
由于没有第三方服务器,每个Client都可以兼职做Host。到这里,你是不是想到了局域网游戏?由于没有服务器,第一个创建的玩家便是主机。当他退出时,主机就交给了第二个玩家。如果他没按正常步骤,强制退出了游戏,那就很有可以造成主机丢失,数据没来得及转移给下个玩家,导致游戏断线结束。
同样,当我们Host所在页面关闭时,会向所有Client发送一条退出消息。至于谁继承王位,不用关心,谁先得知谁做~~ 唯一值得注意的就是:很多浏览器不能正常触发window.unload事件,这意外着Host可能还没来得把回调列表移交给他的继承者就已匆匆离去,于是后人就无法接管了。为了不让这种情况出现,每当新的Host上任,就向所有的Client发送一个请求,让大家把各自关注的主题重新发送一遍(之前关注的都保存着,就为了这个时候用)。因此,即使新上任的Host一无所有,大家也会把现状告诉他,可立即投入工作中。
若是强制关闭了Host所在的页面进程,那么主机丢失后一切都将会挂起。这时所有Client发送的数据都将有去无回,只有等到之后出现数据发送失败,才得知Host已经挂了。这时谁先发现这个错误,谁就接管Host工作吧。
当然,还可以考虑加上心跳机制,即使Host没有挂掉,但其所在进程长时间占用CPU,导致LocalConnection无法响应消息事件,也可以考虑转移Host了。
由于时间限制,本例还有不少BUG,以后再慢慢完善。
想看代码可以浏览:http://code.google.com/p/webipc/source/browse/
事实上纯粹的本地通信意义并不大,只有配合远程服务进行消息的交互,才更有意义。例如用户开了多个微博页面,传统的模型必须为每个页面发起一个长连接,来保持实时的数据接收。如果使用跨浏览器通信,那么只需让Host发起一个连接即可,其余的Client订阅自己想要的主题,最终只需一个连接就可以。


猜你喜欢
- 今天我们来学习,如何使用有趣的自定义标记来布局页面。有的朋友可能有这样的疑问,自己随便定义的标记浏览器怎么能正确的认识呢?这里我们就要用到文
- 1.1MyBatis简介 MyBatis 是一个可以自定义SQL、存储过程和高级
- pandas转数组np.array(pandas)数组转pandaspandas.DataFrame(numpy)pandas连接,只是左右
- 在Python中是没有Switch / Case语句的,很多人认为这种语句不够优雅灵活,在Python中用字典来处理多条件匹配问题字典会更简
- Go语言中符号 “ ^ ” 不再用于次方,而是表示“按位异或的运算”具体的运算规则如下:按位异或 ^ : 两位一个为 0, 一个为 1 ,结
- 一、前言前几天在Python最强王者群有个叫【dcpeng】的粉丝问了一个关于Pandas中的问题,这里拿出来给大家分享下,一起学习。想问一
- MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Win
- 本文主要研究的是Python编程删除服务器文件,具体实现 代码如下。实例1#coding:utf-8import paramiko"
- web跨域请求1.为什么要有跨域限制举个例子:1.用户登录了自己的银行页面 http://mybank.com,http://mybank.
- 在网页中放iframe,如果frameborder=0;就没有边框显示了;但动态创建时,在IE7中就不行了,从网上找到解决的办法,写出来记录
- 这篇文章主要介绍了Python动态声明变量赋值代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- Nodejs 的大部分核心 API 都是基于异步事件驱动设计的,事件驱动核心是通过 node 中 Events 对象来实现事件的发送和监听回
- 本文为大家分享了TensorFLow用Saver保存和恢复变量的具体代码,供大家参考,具体内容如下建立文件tensor_save.py, 保
- 一、说明之前写了一篇“Python执行系统命令教程”讲了如何执行系统命令。除了执行系统命令外,我们有时还需要动态地执行一些python代码,
- 前言:我们在做自动化测试的时候,大家都是希望自己写的代码越简洁越好,代码重复量越少越好。那么,我们可以考虑将request的请求类型(如:G
- python中通过虚拟化出来一个空间,与主环境完全隔离,避免项目中对于环境要求,造成的插件版本混乱(python特别吃环境)mac 的配置前
- 程序运行前加载1.导包前面加下划线,运行前加载2.把要加载的写在init函数里面路由设置路由的作用:根据不同的请求指定不同的控制器路由函数:
- 作为一个网页设计师,不知道各位是否有这样的经历:客户给你的网站材料很多都是Word文档,虽然阅读起来很
- 五种Python下划线模式速查表:单前导下划线:_var当涉及到变量和方法名称时,单个下划线前缀有一个约定俗成的含义。 它是对程序员的一个提
- opencv > pilimport cv2 from PIL import Imageimg = cv2.imread("