>  기사  >  웹 프론트엔드  >  웹 크로스 브라우저 프로세스 통신(웹 크로스 도메인)_javascript 기술

웹 크로스 브라우저 프로세스 통신(웹 크로스 도메인)_javascript 기술

WBOY
WBOY원래의
2016-05-16 17:36:321550검색

  在之前一篇文章里尝试了跨浏览器的数据共享,最后提到使用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。到这里,你是不是想到了局域网游戏?由于没有服务器,第一个创建的玩家便是主机。当他退出时,主机就交给了第二个玩家。如果他没按正常步骤,强制退出了游戏,那就很有可以造成主机丢失,数据没来得及转移给下个玩家,导致游戏断线结束。

마찬가지로 호스트가 있는 페이지가 닫히면 모든 클라이언트에게 종료 메시지가 전송됩니다. 누가 왕좌를 물려받을지는 걱정하지 마세요. 먼저 아는 사람이 할 것입니다~~ 주목할 점은 많은 브라우저가 window.unload 이벤트를 정상적으로 트리거할 수 없다는 것입니다. 이는 예기치 않게 호스트가 이벤트를 처리할 시간이 없다는 것을 의미합니다. 그는 후임자에게 회신 목록을 넘기고 서둘러 떠났기 때문에 미래 세대가 인계받을 수 없었습니다. 이러한 상황을 방지하기 위해 새로운 호스트가 취임할 때마다 모든 클라이언트에게 관심 있는 주제를 다시 보내도록 요청하는 요청이 전송됩니다. (이전 주제는 모두 이번만 저장됩니다.) ). 따라서 새로운 호스트가 아무것도 갖고 있지 않더라도 모든 사람이 그에게 현재 상황을 알려주고 그는 즉시 작업에 착수할 수 있습니다.

호스트가 위치한 페이지 프로세스가 강제로 닫히면 호스트가 손실된 후 모든 것이 중단됩니다. 이때 클라이언트가 보낸 모든 데이터는 결코 반환되지 않습니다. 나중에 데이터 전송이 실패할 때만 호스트가 끊겼다는 것을 알 수 있습니다. 이때, 이 오류를 먼저 발견한 사람이 호스트 작업을 맡게 됩니다.

물론, 호스트가 중단되지 않지만 해당 프로세스가 CPU를 오랫동안 점유하여 LocalConnection이 메시지 이벤트에 응답할 수 없는 경우에도 하트비트 메커니즘을 추가하는 것을 고려할 수도 있습니다. 호스트를 이전합니다.

시간의 제약으로 인해 이 예시에는 아직 버그가 많이 남아 있으며, 향후 점진적으로 개선될 예정입니다.

코드를 보려면 http://code.google.com/p/webipc/source/browse/

에서 찾아보세요.

사실 순수 로컬 통신은 별 의미가 없습니다. 원격 서비스와 협력하여 메시지를 주고받는 것만으로는 더 의미가 없습니다. 예를 들어 사용자가 여러 Weibo 페이지를 여는 경우 기존 모델은 실시간 데이터 수신을 유지하기 위해 각 페이지에 대해 긴 연결을 시작해야 합니다. 브라우저 간 통신을 사용하는 경우 호스트가 연결을 시작하고 다른 클라이언트가 원하는 주제를 구독하도록 허용하면 되며 궁극적으로 하나의 연결만 필요합니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.