HTML 5案例研究:使用WebSockets、Canvas与JavaScript构建noVNC客户端

noVNC是个VNC客户端,采用HTML 5 WebSockets、Canvas和JavaScript实现。近日,InfoQ有幸采访到了Joel Martin以了解noVNC及其在HTML 5应用开发上的经验:

InfoQ:Joel,能否谈谈noVNC的整体架构,各个组件是如何搭配到一起的?

Joel:noVNC的架构主要由以下6个组件构成:
  • 核心的VNC/RFB实现:该组件封装了所有的RFB协议相关的内容,是驱动其他组件的主要状态机。
  • Canvas抽象:该组件为HTML5 canvas API提供了一个抽象,还会进行Canvas特性检测,对于没有完整支持HTML5 canvas规范或是实现有问题的浏览器,组件会采取其他一些办法解决这个问题。
  • 用户界面:封装了所有的HTML DOM交互(除了canvas)。该组件会渲染页面控件,如连接/断开连接按钮、设置以及状态反馈。noVNC的一个设计目标就是要能轻松加到现有的套件当中,因此该组件是可选的。
  • 辅助功能:包含了noVNC所用的一些杂项功能与扩展,包括对JavaScript数组的扩展(使之可以当作队列使用)、跨浏览器的事件处理以及调试与日志等。我还会从其他一些资源中引入一些JavaScript库以处理base64编解码和DES加密(用于VNC认证)。
  • WebSockets回退:现在的大多数浏览器都没有本地的WebSockets支持,因此我为这些浏览器添加了一个Flash(Flex)仿真器,使用WebSockets加密技术扩展了最初的项目。
  • WebSockets到TCP的代理:WebSockets标准并非纯粹的TCP socket实现。标准中有类似于HTTP的握手以建立初始连接,接下来的每一帧都以0字节开始,255字节结束。在VNC服务器开始支持WebSockets前( 我很希望能做到这一点),我们还是需要代理在WebSockets和标准的TCP sockets之间进行转换。我已经实现了一个通用代理(有Python和C两个版本),这对于那些从事着WebSockets开发的人来说有一定的帮助作用。

InfoQ:在开发HTML5应用时遇到的挑战主要有哪些?开发者需要提防哪些陷阱呢?

Joel:主要的挑战在于对那些缺乏HTML5特性以及只支持部分HTML5特性、甚至连部分特性都支持不好的浏览器提供回退支持。比如说,虽然Chrome 5和Safari 5都提供了本地的WebSockets支持,但当前版本的Firefox和Opera则不支持。一些老版本的浏览器也没有提供canvas像素操纵API(更糟的是,有的浏览器虽然提供了支持,但一使用Arora 0.5就崩溃了)。已发布的各个版本的Internet Explorer都没有内置WebSockets,甚至连最基本的内置canvas支持都没有(IE 9 Preview开始提供canvas支持)。另一个挑战在于跨越多个浏览器的性能优化问题。每个浏览器都有不同的性能特质,在同一浏览器的不同版本中这一点也不尽相同(甚至同一个浏览器的不同操作系统版本也不一样)。只有很少的地方需要使用到浏览器检测技术,但对于性能优化问题,我觉得浏览器检测技术是必不可少的。

InfoQ:你都使用了哪些工具?目前的开发工具足以承担起构建HTML5应用的重任么?你希望今后能出来哪些新工具呢?

Joel:我的开发环境非常精简,使用vim(加上很多扩展)在Linux上编写代码。频繁使用firefox上的firebug和Chrome中内置的开发者工具进行调试与分析。我还使用了Crockford的JSLint以保持JavaScript代码的整洁性。

我希望firebug与Chrome中的分析工具能给出比函数级别粒度更细的反馈信息,能告诉我们哪部分代码对垃圾收集产生了重要影响。现在noVNC代码还在不断优化,垃圾收集器已经成为一个主要的性能瓶颈,我开始深入到其中解决问题了。

我希望出来的新工具是代码分析器(就像JSLint那样),可以扫描Javascript代码基并生成好看的浏览器支持表格。我期望的输出形式是这样的:上面是代码中所用的特性列表,左边则是主要的浏览器与版本号。接下来,每个单元格就会报告代码使用特性的方式是否为给定的浏览器/版本所支持。虽说这么做并不会导致不同浏览器上代码测试的工作量,但毫无疑问,它有助于我们在开发过程中了解是否已经偏离了轨道。在理想情况下,扫描器还应该检测出Javascript是否针对某个特性使用了恰当的检测/问题解决办法。

InfoQ:对于目前的规范与实现来说,要克服的局限性主要有哪些呢?

Joel:值得庆幸的是规范做的很棒。

RFB(VNC)协议的文档在这里 http://tigervnc.org/cgi-bin/rfbproto。

这个站点提供了很好的Javascript参考信息(包括哪个浏览器版本支持哪些特性): http://www.hunlock.com/

我发现一个非常棒的站点,里面归纳了哪些浏览器支持哪些特性(涵盖了HTML5等内容),网址是 http://caniuse.com/。站点 http://quirksmode.org更是无价之宝(这就是著名的PPK站点,他是知名的JavaScript图书PPK on JavaScript的作者——译者注),详尽列出了哪些浏览器支持哪些API以及如何解决众多的限制。我要克服的最困难的浏览器限制就是缺乏本地的跨浏览器WebSockets支持。这是最近才出来的标准,还处在变更当中,但很多浏览器都纷纷采用了该标准。目前webkit支持该标准,因此Chrome 5和Safari 5都支持,不久之后iPhone也会支持。firefox 4可能也会加入对其的支持。当然了,Opera也会在不久的将来支持它。最大的问题在于IE 9是否会支持。

如前所述,我使用Flash WebSockets仿真器来支持那些没有本地支持的浏览器。扩展、修复以及解决Flash(ActionScript)代码中的bug是个艰巨的任务。桥接Javascript和Flash也是个让人头疼的问题。Adobe提供了FABridge(仿真器使用到了),但这个桥太慢、太笨重,难以调试。

听说IE 9将提供完整(速度也很快)的canvas支持后我感到兴奋异常,但我还得解决旧版本IE缺乏本地canvas支持这个局限性,因为IE用的实在是太多了。现在有两个办法,一个是explorercanvas,另一个是fxcanvas。前者是个JavaScript库,它基于IE的VML支持创建了一个canvas API;后者则是个canvas的Flash实现,但这两个办法都不是十全十美的。Explorercanvas不支持像素操纵(这是因为VML是矢量而非光栅),而fxcanvas则提供了一个类似于canvas的API,它存在一些严重的异步处理问题。遗憾的是,相对于其他支持canvas模拟的浏览器来说,IE 6、7和8中的JavaScript引擎太慢了,这两个办法都没法很好地应用到IE上,现在我只能期望人们使用Chrome Frame了。

InfoQ:关于noVNC项目,未来的计划如何?

Joel:现在,我感觉最兴奋的事情就是能与一些QEMU/KVM开发者们(包括一个Google编码之夏的学生)一起工作来设计新的VNC编码器,新的编码器针对浏览器渲染进行了大量的优化,这个新的VNC/RFB编码器会以PNG格式传输图像数据。除了极佳的无损图像压缩外(相对于紧密编码来说),浏览器几乎不需要什么解码工作就能渲染PNG数据流(这一点与紧密压缩大不相同)。
WebSockets到TCP sockets代理的需求对于noVNC的普及是个障碍,我希望VNC服务器能加入WebSockets支持,现在我的主要精力都放在了libvncserver(用于构建不同的VNC服务器)和QEMU/KVM上,但还是希望能帮助并鼓励其他的VNC服务器开发者增加对WebSockets的支持。将WebSockets支持加到其他的VNC客户端用处也很大,因为WebSockets协议设计之初就考虑到支持的方便性并且可由Web服务器代理(因此会有兼容于HTTP的握手)。这将有助于解决VNC的一个老大难问题:与防火墙的交互。

之所以把这个项目命名为“noVNC”,一个原因是我还希望出现其他的“虚拟网络计算机”协议的实现,比如RDP、NX以及Red Hat的Spice协议。

如果iPhone能增加本地的WebSockets支持(显然Flash的回退已经超出了问题本身),我就会让noVNC运行在iPhone之上。我想增加的一个非常有用的特性是视角与缩放支持,这对于智能手机来说也非常关键。对于Google来说,如果能在Android上支持noVNC将是一件多么美妙的事情啊。

Guacamole项目也采取了类似的处理方式,它同样是一个HTML5 VNC查看器,利用了服务器端的代理,它使用Java编写。目前版本的响应速度号称可以达到VNC的水平,只要浏览器支持HTML5 canvas标签就可以使用Guacamole。

感兴趣的读者可以在InfoQ上找到关于HTML5RIA的更多信息!

查看英文原文:HTML5 Case Study: Building the noVNC Client with WebSockets, Canvas and JavaScript

你可能感兴趣的:(HTML 5案例研究:使用WebSockets、Canvas与JavaScript构建noVNC客户端)