FlyWeb – 纯粹的跨设备网页交互

FlyWeb 是一个实验性项目,我们一直在 Mozilla 平台部门的深处进行原型设计。它起源于去年年底的一个副项目,从那时起,一个小型、非正式的团队一直在致力于实现该概念的“版本零”。在过去 6 个月里,我们一直在改进实现,现在已经到了我们可以放心地谈论它的阶段,特别是对于那些可能对它提出的想法感兴趣的 Web 开发人员和硬件黑客们。

从根本上来说,我们的目标是:让在物理上靠近的人或设备能够轻松地互相流式传输应用程序和内容。为了实现这一点,我们希望让任何人能够轻松地搭建一个“局域网服务器”,并且可以让使用浏览器的其他人发现并连接到该局域网服务器。在这个架构之上构建了什么,就取决于你和其他开发人员/黑客。

FlyWeb 服务器可以驻留在你计算机或智能手机上加载的网页上,也可以驻留在你网络上的小型硬件设备上。FlyWeb 服务器并非设计为可被“互联网”访问,而仅限于本地网络上的用户访问(即,已经在物理附近的人)。

FlyWeb Architecture Diagrams

FlyWeb 的设计很简单。FlyWeb 服务器是一个 Web 服务器,它使用 mDNS 在本地网络上进行自我宣传。在 Firefox Nightly 中,我们添加了一个小型 UI 元素,让你可以列出本地宣传的 FlyWeb 服务(默认情况下关闭,只有在 dom.flyweb.enabled 配置首选项为真时才会激活)。当你选择要连接的服务时,浏览器会为该服务创建一个唯一的“UUID 主机名”,并将所有带有该主机名的 URL 路由到该服务。此外,我们使用新的 navigator.publishServer() 函数扩展 Web API,该函数允许网页在本地网络上发布 FlyWeb 服务器。系统会提示用户允许网页执行此操作。

这种设计支持两大类用例。一类与浏览器之间的交互有关,另一类涉及浏览器与想要向用户公开 UI 的“智能硬件”之间的交互。两者都使用相同的架构进行处理。

浏览器到浏览器的交互

假设你编写了一个专为智能手机设计的多人游戏。这里我说的不是 MMORPG,而是指在同一房间里由一群人玩的游戏,比如数字版卡坦、拼字游戏或扑克游戏。你有以下几种选择

1. 编写一个智能手机应用程序

这个解决方案可行,但你需要在应用商店发布该应用程序,并让每个人在玩游戏之前都下载该应用程序。如果有人想换一种游戏,他们都必须下载另一种游戏。该应用程序需要使用一些本机通信协议,以便手动发现和连接彼此的手机。

2. 编写一个基于 Web 的游戏

这也是一个合理的解决方案,但有一些问题。每个人都必须访问游戏的网站,并且可能需要在网站上创建帐户(或接收某种唯一的令牌),然后用它来彼此协调。玩家之间的通信必须通过游戏托管的服务器进行转发,这意味着需要低延迟输入的游戏很难或不可能实现。此外,所有参与游戏的玩家都必须连接到互联网。

FlyWeb 方法

以上两种方法都会造成很大的用户摩擦。使用 FlyWeb,你可以将游戏设计为 Web 游戏,但不再使用云来实现多人游戏,游戏本身可以托管本地多人游戏体验。以下是具体操作方法

  1. 小组中的一人加载游戏网站,并要求游戏开始一个新的多人游戏会话。
  2. 游戏会调用 navigator.publishServer()(一个 FlyWeb API)来发布一个局域网服务器。publishServer 返回一个 Promise,它解析为一个 FlyWebPublishedServer 对象,游戏会在该对象上绑定 HTTP/WebSocket 请求的事件处理程序。
  3. 朋友们可以通过浏览器发现游戏,并直接连接到游戏。
  4. 当他们连接时,主机网页的 FlyWebPublishedServer 事件处理程序会被调用。主机网页充当 Web 服务器,并向所有连接器提供其自身的一个副本(并跟踪它们)。“客户端”网页可以建立一个 WebSocket 连接返回到主机网页,如果游戏需要低延迟通信的话。
  5. 每个人一起玩。就游戏而言,主机网页和玩家网页之间的通信使用标准的 Web 技术(如 HTTP fetch 请求和 WebSocket)来实现。

没有人需要下载应用程序,没有人需要注册帐户,或交叉引用唯一的代码或其他任何复杂的操作。只有托管游戏的浏览器需要连接到互联网才能获取主机“服务器”网页(使用 Service Worker 等新的 Web 功能,甚至不需要互联网连接)。该游戏可以建立在纯 Web 协议上,所有操作都具有低延迟并且可以玩。基本上,无需任何局域网之外的支撑基础设施和支持 FlyWeb 的浏览器,就可以创建多人游戏体验。

例如,Justin 将 FlyWeb 集成到一个基于 Unity WebGL 的赛车演示中,灵感来自 4 人分屏的马里奥赛车游戏玩法,Kannan 在 Mozilla 多伦多办事处举行了一次简短的游戏环节

在我们这个例子中,笔记本电脑浏览器充当“控制台”,智能手机 FlyWeb 客户端充当游戏控制器。智能手机浏览器会发现并连接到笔记本电脑网页上托管的游戏服务器,并接收一个“控制器 UI”网页。手机上的这个控制器网页会建立一个 WebSocket 连接返回到主机网页,并使用它将触控和转向输入发送回去。

如果你有一部 Android 手机和一台笔记本电脑,你今天就可以玩这个演示(如果你想的话,还可以下载源代码并进行修改)。只需访问 flyweb.github.io 并按照说明操作,然后访问该页面的“Showcase”部分,以获取演示的链接。该游戏通过 GitHub Pages 托管,源代码可在我们的 GitHub 仓库 中的“flyweb-gp”文件夹中找到。

你还可以查看该 GitHub 仓库中的“flyfile”和“photo-wall”子文件夹,以了解更简单的基于 Web 的文件共享在智能手机之间的演示。

智能硬件

假设你正在构建一个硬件设备。也许它是一款新式智能恒温器,或者你自制的四轴飞行器。太好了!现在你需要一个 UI 来控制它。你可以选择以下几种方案

1. 编写一个智能手机应用程序

这可能是第一个想到的方案,但它有一些问题。编写智能手机应用程序很困难。你需要设置一个开发环境,下载 SDK/构建工具以及你选择的平台的所有其他东西。你需要编写应用程序,将其编译成一个包,并将其加载到你的手机上。如果你希望其他人能够轻松使用你的应用程序,你需要在应用商店发布它(希望它能被接受)并维护它。这是一个非常大的麻烦。

此外,你还需要为想要支持的每个不同的平台构建这个应用程序。你想从 Windows 或 Mac 笔记本电脑访问它,除了你的手机?再写一个应用程序。这绝对不是最方便的开发体验。

2. 构建一个从你的设备提供的 Web UI

这种方法简单得多。你不需要构建一个原生应用程序。UI 在不同的平台上都能正常工作。你不需要在应用商店托管应用程序。你不需要构建一个应用程序包来分发以供侧载。但是,访问 UI 很难。你必须打开浏览器,以某种方式找出设备的 IP 地址,然后输入它。

这种方法也很容易出错。如果你后来碰巧在其他局域网(例如 192.168.1.1:80)上以相同的私有 IP 地址访问其他服务,则该服务可能会窃取第一个服务存储的 cookie。这些服务在使用缓存时必须小心,因为当你访问第二个服务时,你可能会获得第一个服务的缓存页面。

FlyWeb 方法

FlyWeb 的方法基本上是选项 2,但加入了一些额外的魔法。第一个魔法是通过 mDNS 进行宣传,以及一个浏览器 UI 来按名称发现服务,而不是必须手动找出并输入 IP 地址。第二个魔法是生成唯一的 hostname。目前,每次连接到服务时,浏览器都会生成一个 UUID 用作该服务的 hostname。没有两个 UUID 会在服务之间共享,因此我们可以避免诸如泄漏 cookie 或缓存交叉污染等问题。

在才华横溢的 Kate Glazko 的帮助下,我们构建了一个演示,展示了这种方法如何使用 Parrot AR 四轴飞行器和 Raspberry PI(控制飞行器并公开一个 FlyWeb 服务器),并在 2016 年 6 月的 Mozilla 全体会议上进行了展示。这是一段演示视频

本演示的源代码也包含在我们的 示例仓库 中(在 flyweb-quadcopter 文件夹下)。我们已经构建了其他基于硬件的演示,例如 ESP8266,它是一款仅售 5 美元的带有嵌入式微控制器的 WiFi 芯片。FlyWeb 服务器可以在极其简陋的硬件上运行。即使是微小的、低功耗的设备也能呈现非常丰富的 UI,因为 Web 平台允许它们将控制 UI 动态流式传输到更强大的智能手机或计算机。

下一步

目前,此功能仅在 Firefox Nightly 中实现并公开(未在 Aurora 或 Beta 中),并且隐藏在默认情况下关闭的偏好设置后面。当前实现基本上是“版本 0”实现,足以构建一些非常棒的演示,并体验 FlyWeb 的潜力。

团队目前的目標是讓早期採用者開發者和愛好者使用這個實現,並就该功能作为未来“真正”的 Web 标准的可行性提供反馈。如果您是希望创建简洁的多用户“本地区域”体验的 Web 开发人员,或者您是希望为您的作品提供 UI 的硬件黑客,我们希望您能尝试一下,玩一玩,并告诉我们您的想法。

如果您對此功能的潛力感到興奮,想用它来构建东西,或帮助进行实现(我们的团队只有 2 人,我们不是什么大型项目——这实际上是一个实验性的“秘密项目”),请访问我们的网站 flyweb.github.io。您也可以在 Slack 上与我们聊天 mozflyweb.slack.com(注册 此处)或在 Twitter 上关注我们 @MozFlyWeb

注意事项

请记住,这是一个非常早期的实现。可能存在错误和安全问题。如果您确实尝试使用 FlyWeb,我们建议您为此目的创建一个新的 Firefox 配置文件,并建议您不要使用该配置文件浏览通用网络。仅使用单独的配置文件运行 FlyWeb 演示或您自己的代码。

快乐地进行黑客攻击!:)

关于 Kannan Vijayan

Kannan 是一位系统开发人员,他构建了从 RNA 序列分析的 Web 工具到 Javascript 引擎的 JIT 编译器,从嵌入式操作系统的红外堆栈到实验性的新 Web 平台技术,无所不包。如果您有几个小时的时间浪费在听他讲这些东西,可以问他任何关于以上内容的问题。

Kannan Vijayan 的更多文章…

关于 Justin D'Arcangelo

Mozilla 的软件工程师,创建最前沿的移动 Web 应用程序。自豪的父亲、丈夫、音乐家、黑胶唱片爱好者和全能的修补匠。

Justin D'Arcangelo 的更多文章…


28 条评论

  1. Endyl

    我一直在寻找这样的东西(主要是用于本地多人游戏)。不幸的是,只有 FlyWeb 远程在我的机器上运行,其他示例会导致主机浏览器崩溃。

    我希望它得到广泛采用。

    2016 年 9 月 6 日 下午 11:01

    1. Kannan Vijayan

      嗨 Endyl,

      崩溃令人困扰。您的 Nightly 什么时候崩溃的?您在崩溃之前是否收到允许发布服务器的提示?它在 Nightly 上崩溃时没有将“dom.flyweb.enabled”设置为 true(即 FlyWeb 功能关闭)吗?我非常有兴趣追踪和解决这个问题。

      2016 年 9 月 6 日 下午 12:48

      1. Endyl

        崩溃发生在客户端连接之后。客户端接收初始响应(GP 示例的踏板或其他示例的照片墙 UI 出现在客户端),然后主机崩溃。主机浏览器在连接从另一个设备(Android 5.1.1 上的 Nightly)或从同一个设备(使用另一个配置文件和 –no-remote 开关)连接后,在 Win7 和 Ubuntu 14.04 上也崩溃了。

        据我所知,FlyWeb 远程示例运行没有问题。此外,我能够访问网络打印机和家庭服务器 GUI(我猜是因为它们使用 mDNS 进行广播),这是一个惊喜(无需查找设备的 IP)。

        2016 年 9 月 7 日 上午 1:01

        1. Kannan Vijayan

          酷。是的,打印机和其他服务发现是因为除了发现 FlyWeb 服务(_flyweb._tcp.local)之外,我们还列出了(_http._tcp.local)服务,很多打印机都在这些服务上提供 Web UI。

          感谢您提供崩溃信息。我尝试在我的机器上重现它,但我遇到了麻烦。您是否有兴趣在 bugzilla 错误中跟进此事?我已经在这里创建了一个错误:https://bugzilla.mozilla.org/show_bug.cgi?id=1301091

          2016 年 9 月 7 日 上午 8:29

          1. Endyl

            当然。我很快会在那里添加评论,提供更多细节。

            2016 年 9 月 7 日 下午 12:23

          2. Kannan Vijayan

            感谢 Endyl。我认为我已经追踪到您看到的崩溃(相同的重现条件)。为了验证,您启用了 e10s 吗?

            我现在正在编写修复程序,希望能够确保它正常运行,并尽快发布它,以便在明天的 Nightly 版本中提供。

            2016 年 9 月 7 日 下午 2:18

          3. Endyl

            是的,e10s 已启用。

            期待修复程序可用后,可以对其进行修补!

            2016 年 9 月 8 日 上午 1:45

  2. Perry

    您能解释一下这与 bonjour/avahi 等其他 zeroconf 东西有什么不同吗?它是否只是特定于 Web 应用程序,并且在“唯一主机名生成”中?我不太明白,主机名是指客户端设备吗?

    2016 年 9 月 6 日 下午 8:22

    1. Kannan Vijayan

      嗯,zeroconf 的范围比服务广告要广。我们只是使用 mDNS+DNS-SD(即 Bonjour/Avahi,但它们是实现的品牌名称)。FlyWeb 服务只是 mDNS 广告的“_flyweb._tcp.local”服务,它们指向本地网络上的 Web 服务器。对于广告,有一些额外的协议支持,以便嵌入证书信息,以备将来加密传输支持(目前我们已经实现了自签名证书)。

      我们添加的语义预期是,浏览器在与给定服务“建立会话”时,应该为该服务分配一个“主机名”,该主机名永远不能被其他服务使用。此生成的“主机名”对浏览器来说是内部的,并充当基于 DNS 的名称解析的替代方案。目前,我们只是为建立的每个会话生成随机 UUID。这以一种非常强制的方式解决了基于来源的安全问题:没有两个会话会共享主机名,因此它们将永远不会具有相同的来源。

      展望未来,在服务广告元数据中存在公钥信息的情况下,我们可以为该服务分配一个“稳定”的主机名,该主机名仍然满足上述条件。我们通过生成一个服务名称来实现这一点,该名称嵌入了该公钥的指纹/摘要。稍后,在连接到相同服务时,我们可以可靠地分配相同的名称,前提是验证该服务实际上控制与公钥关联的密钥对。这将为我们提供稳定的命名,但也确保没有任何服务能够伪装成其他服务(除非以某种方式获取密钥对)。

      这种解释更清楚了吗?

      2016 年 9 月 7 日 上午 8:44

  3. Gervase Markham

    当您说“2015 年 6 月”时,您的意思是“2016 年 6 月”吗?

    2016 年 9 月 7 日 上午 7:22

    1. Kannan Vijayan

      是的。是的,我的意思是。我会改正的。谢谢!

      2016 年 9 月 7 日 上午 8:45

  4. wryk

    看起来很有希望,但当我尝试发布服务器时,我遇到了 NS_ERROR_FAILURE 错误。(在 github 页面和本地尝试了 flyfile、flyweb-gp 和 photo-wall)

    2016 年 9 月 7 日 上午 8:31

    1. Kannan Vijayan

      您在哪个平台上运行?

      2016 年 9 月 7 日 上午 8:46

      1. wryk

        我的桌面使用 Win8.1 运行 Firefox 开发版 50.0a2。
        我的智能手机使用 Android5.1 运行 Firefox Nightly 51.0a1。(只用它尝试了 flyfile)

        2016 年 9 月 7 日 上午 8:59

        1. wryk

          这里快速更新一下

          桌面上的最新 Nightly(51.0a1)代替开发版,以及我的智能手机上的最新 Nightly 更新修复了我的 NS_ERROR_FAILURE 错误。
          对不起,伙计们,这两种情况都只是版本问题:/

          2016 年 9 月 8 日 上午 7:41

          1. Kannan Vijayan

            很高兴听到。奇怪的是它怎么会发生。如果它再次发生,请告诉我们。

            2016 年 9 月 9 日 上午 8:46

  5. Pierre

    作为一个小问题,我尝试在我的本地 WiFi 网络上使用“.local”地址。它在我的 Linux 笔记本电脑上运行良好,但我认为当我想要从我的 Android 手机(使用 Firefox Android)访问我的笔记本电脑(运行“python -m SimpleHTTPServer 8000”进行测试)时,它会失败。

    快速搜索后,我发现 Android(*) 上的 mDNS 支持并不理想,但 Firefox Android 是否计划支持它?

    (*) Chrome 的说明:http://android.stackexchange.com/questions/49188/how-to-get-mdns-working-for-chrome-on-android

    2016 年 9 月 7 日 下午 12:43

    1. Kannan Vijayan

      您是否在 Android 上使用 Nightly 版本?您需要从 nightly.mozilla.org 获取 Firefox nightly apk 并直接安装,然后在 Android 的 Nightly 版本中启用“dom.flyweb.enabled”选项,最后使用该浏览器。

      2016 年 9 月 7 日 下午 14:14

      1. Pierre

        感谢您的反馈。确实,我使用的是 Android 版的稳定版 Firefox。我理解 Flyweb 需要 nightly 版本,但我以为 mDNS 是一个独立且已有的功能。

        另外,前几天我想报告我的 Linux 机器(Debian 测试版)上演示程序崩溃了。我尝试使用 GP 演示程序,但使用同一个浏览器(一个标签页显示比赛,另一个标签页进行控制)。不过,我今天(使用 nightly 2016-09-17 版本)再次尝试,现在运行正常了。(当然,使用鼠标和键盘无法真正玩,但这是另一个话题 ;-) )

        2016 年 9 月 18 日 上午 06:01

  6. Caspy7

    一个强大但简单的应用是将它用于幻灯片演示。

    它可以在学校、学院、会议、商业环境等场所使用 - 无论是否使用主显示器进行演示。只需出现,连接到演示者的服务器即可。
    潜在功能包括
    – 观众反馈,例如投票
    – 允许用户返回到之前错过的幻灯片(在他们的设备上)
    – 轻松保存整个演示文稿或仅截取单个幻灯片的屏幕截图

    尤其适用于并非每个人都能清楚看到主屏幕或没有主屏幕的环境。
    此外,大屏幕可以是支持 Flyweb 的电视或投影仪。

    另一个用途是简单地与朋友分享照片。

    2016 年 9 月 7 日 下午 21:58

  7. 所以

    题外话,但在我看来仍然很重要

    很讽刺的是,作为 Mozilla 的成员,你们宣传使用 Slack 进行交流,却没有宣传自己的 IRC 频道(#flyweb on irc.mozilla.org)。

    我以为 Mozilla 的核心原则之一是开放性。看看 https://www.mozilla.org/。那么,首先列出公开的交流方式,然后 - 如果需要的话 - 列出封闭的数据孤岛,难道不合适吗?

    最令人啼笑皆非的是,你们为邀请用户加入 Slack 频道开发的应用程序。非常有创意 - 而且耐人寻味。

    2016 年 9 月 9 日 上午 04:06

    1. Kannan Vijayan

      关于没有列出 IRC 频道,您说得对。我们将在 Flyweb 主页添加该信息。我不知道您所说的“邀请自己加入”Slack 的应用程序是什么意思。您指的是什么?

      您对没有列出 IRC 频道这件事想得太多了。这个项目只有两个人负责编码、调试、网站、通讯、博客文章和演示。事情总会遗漏。感谢您提醒我们漏掉了 IRC 频道。

      2016 年 9 月 9 日 上午 08:52

      1. Justin D’Arcangelo

        实际上,#flyweb IRC 频道的信息已经发布在我们的网站上,我们可能只是不小心没有在这篇文章中提到它。我们还能够在 IRC 频道和 Slack 频道之间“镜像”对话,这样无论参与者在哪个地方都不会错过任何信息。我们创建 Slack 频道的理由主要是为了为那些不常使用 IRC 频道的人提供另一个参与项目的渠道。

        另外,我不确定您所说的邀请新用户加入 Slack 频道的应用程序是什么意思。我们在 https://mozflyweb-slack-invite.herokuapp.com/ 上发布的网页允许*任何用户*自动加入我们的 Slack 频道,无需通过来回邀请流程。您只需在其中输入您的电子邮件地址,您就会自动“被邀请”(用 Slack 的术语来说)。

        2016 年 9 月 9 日 上午 10:05

  8. Kartik Rishi

    我认为这对于在飞机上进行朋友之间的小组对等消息传递非常有用。想象一下,你和朋友一起旅行,但分散坐在飞机上的不同座位上。为了互相聊天,可以开通一个无线热点,让其他朋友连接,然后主机只需启动一个预先确定的地址,该地址承载所有个人之间进行消息传递的应用程序。

    2016 年 9 月 10 日 下午 18:43

    1. Justin D’Arcangelo

      这是一个非常酷的用例!我们的团队实际上已经确定“离线旅行”是一个特定的场景,我们认为 FlyWeb 有潜力在这样的场景中实现各种有趣的应用程序。我们经常错误地认为用户会一直有连接,但正如您所知,情况并非如此。即使在您可以访问 2G 蜂窝网络的情况下,有时也和*没有*连接一样糟糕。另一个值得注意的场景是,一群朋友去没有蜂窝网络的地区远足,他们仍然可以通过离线 Flyweb 应用程序互相发送消息/照片。

      2016 年 9 月 13 日 上午 11:08

      1. Jim Porter

        离线 Flyweb 应用程序的另一个潜在场景是,当您*有*连接,但使用连接很昂贵(例如,您在另一个国家,您的手机计划在漫游时收取大量数据费用)。

        关于 Kartik 建议的应用程序,我实际上正在开发一个可能非常适合它的项目,叫做“Project Refrigerator”[1]。它是一个多人绘画/聊天应用程序,使用 Flyweb 为附近的用户创建连接通道。现在公开宣传还为时过早,但希望在下周左右会有关于它的 Hacks 文章。:)

        [1] https://github.com/jimporter/refrigerator

        2016 年 9 月 29 日 上午 11:31

  9. Jakob

    我认为在某种程度上,如果 Web 想成为 P2P 用例(我认为包括物联网)的可行平台,它必须解决对 TCP 的极度依赖。与其将 TCP 拼接到 BLE 或 UDP 协议(这些协议对于 NAT 穿越是必要的),我认为如果浏览器和 Web 应用程序可以选择原生支持此类协议,会更好。

    我很高兴您正在解决证书问题和本地服务的可发现性问题。我只是希望长期计划不要仅仅依赖于局域网和缺乏会使 mDNS 无法正常工作的组播数据包过滤器。

    2016 年 9 月 11 日 下午 12:28

  10. Chi-Jui Wu

    很酷的东西。我刚刚注册了 Slack 频道。可能会用它构建一些跨设备的东西。

    2016 年 9 月 27 日 下午 22:30

本文的评论已关闭。