在Ajax应用程序中实现实时数据推送(下)

日期: 2010-08-10 作者:Sandeep Malik 来源:TechTarget中国 英文

  在《在Ajax应用程序中实现实时数据推送(上)》我们探索讨论了几种模拟服务器推送的方法,从纯轮询到实时服务器推送,说明了每种方法的优缺点。下面我们将探索如何解决上文的第三个和第四个问题。

  基于套接字的RIA技术

  Ajax并不能真正地解决第三个和第四个问题。因而,您需要利用其他RIA技术寻求解决方案。有两种RIA技术提供的套接字API可与Ajax应用程序交互。这两种技术是Adobe Flex和OpenLaszlo。全面介绍这两种技术并非本文讨论范围之内(更多信息请参见 参考资料),但这些技术提供的两种特性如下所示:

  均能通过后端打开TCP二进制套接字均能出色地与运行在同一个浏览器窗口中的Ajax应用程序(主要是JavaScript)交互。但这仅仅解决了部分问题。您确实可以打开套接字,可以使 Ajax 应用程序使用它们,但Ajax应用程序仍然无法处理纯二进制数据。这又该怎么办?实际上,这两种技术都提供了二进制TCP套接字的一种变体,称为XMLSocket,它可用于来回传输纯XML数据。这正是您需要的东西。如果这些技术能够通过服务器打开套接字,如果它们能够传输XML数据,我们的任务就完成了。Ajax应用程序可充分利用这一点,模拟实时服务器推送技术。下面将介绍如何实现。

  实现Ajax服务器推送

  我将使用两种工具解释这项技术:Adobe Flex和OpenLaszlo。首先,您需要编写能够接收并缓存连接的后端服务器。在这里不能太过偏离主题,因而要保证服务器基于阻塞I/O。

  您需要创建一个服务器套接字,接收预先指定地址的连接:

  清单 1. 创建服务器套接字
    

以下是引用片段:
public class SimpleServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket();
        serverSocket.bind(new InetSocketAddress(“localhost”,20340));
        Socket socket = serverSocket.accept();
    }

  在这里,我将服务器套接字绑定到localhost:20340这一地址。当一个客户端连接到该服务器套接字时,它将为我提供一个套接字,显示连接。Flex客户端随后会要求策略文件,这是其安全性模型的一部分。通常,这个策略文件的形式类似于清单 2。

  清单 2. Flex客户端策略文件
    

以下是引用片段:
<?xml version=”1.0″?>
<!DOCTYPE cross-domain-policy SYSTEM 
    “http://www.adobe.com/xml/dtds/cross-domain-policy.dtd”>
<cross-domain-policy> 
<allow-access-from domain=”*” to-ports=”20340″/> 
</cross-domain-policy>         

  就在连接之后,Flex客户端会立即发送一条策略文件的请求。该请求仅包含一个XML标记:<policy-file-request/>。在响应中,您需要返回此策略文件。清单3中的代码就完成了这个任务。

  清单3. 发送策略文件响应
    

以下是引用片段:
public static void main(String[] args) throws IOException {
   ServerSocket serverSocket = new ServerSocket();
   serverSocket.bind(new InetSocketAddress(“localhost”, 20340));
   Socket socket = serverSocket.accept();
   String POLICY_REQUEST = “<policy-file-request/>u0000”;
   String POLICY_FILE = “<?xml version=”1.0″?>n” +
      “<!DOCTYPE cross-domain-policy SYSTEM 
         “http://www.adobe.com/xml/dtds/cross-domain-policy.dtd”>n” +
      “<cross-domain-policy> n” +
      ” <allow-access-from domain=”*” to-ports=”20340″/> n” +
      “</cross-domain-policy>”;
   byte[] b = new byte[POLICY_REQUEST.length()];
   DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
   dataInputStream.readFully(b);
   String request = new String(b);
   if (POLICY_REQUEST.equals(request)) {
       DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
       dataOutputStream.write(POLICY_FILE.getBytes());
       dataOutputStream.flush();
       dataOutputStream.close();
   } else throw new IllegalArgumentException(“unknown request format ” + request);
 }     
    

  此代码建立了与客户端的成功连接。现在,服务器可以与客户端发起 “握手” 之类的协议,此时,服务器通常会指定一个惟一的ID,并将其发送给客户端,此后,服务器可根据ID缓存套接字,在此之后,如果服务器需要向客户端推送某些数据,可以按照ID定位套接字,并使用其输出流。幸运的是,OpenLaszlo也使用了相同的基于策略文件的机制,因而,同样的服务器代码适用于两种场景。

  下面将介绍如何创建Flex套接字,随后将其与Ajax应用程序连接。

  使用Adobe Flex打开客户端套接字

  清单 4 中的代码展示了如何通过Flex打开客户端套接字:

  清单 4. 通过Flex打开客户端
    

以下是引用片段:
var socket : XMLSocket = new XMLSocket();
// register events:
socket.addEventListener(Event.CLOSE, closehandler);
socket.addEventListener(Event.CONNECT, connectHandler);
socket.addEventListener(Event.OPEN, openHandler);
socket.addEventListener(ProgressEvent.SOCKET_DATA, readHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
socket.connect(“localhost”,20340);    

  完成socket.connect()调用后,Flex将向服务器发送一条请求,要求提供策略文件,期待获得XML响应。完成之后,连接即建立,这个套接字现在即可用于从服务器推送数据。

  作为拼图的最后一块,您将看到Flex如何将Ajax作为应用程序调用。为此,要编写一个可处理服务器端消息的通用JavaScript函数。我们将此方法命名为handleServerMessageReceived(message)。此方法会获取来自服务器的XML代码,此方法对于消息的处理方式以应用程序为依据。清单5中的代码展示了Flex如何调用JavaScript函数。这是readHandler方法的代码,该方法在接收到服务器XML消息时被调用。

  清单 5. 使用handleServerMessageReceived(message)的readhHandler代码
    

以下是引用片段:
public  function readHandler(e :  DataEvent) : void {
  var message   : XML = e.data as XML;
  ExternalInterface.call(“handleServerMessageReceived”, message);
}          

  就是这样!就是这样简单。您已经创建了一个XML套接字连接。当来自服务器的数据送达时,您可调用Ajax中的某些通用处理函数,处理这些消息。完整源代码可供下载(请参见下载部分)。

  下面来看看OpenLaszlo如何实现相同的目标。

  使用OpenLaszlo打开客户端套接字

  由于OpenLaszlo应用程序以Flash和DHTML平台为目标,因而其API和脚本语言类似于Flash和JavaScript。这主要是为希望迁移到OpenLaszlo(作为RIA的替代方案)的Web开发人员提供便利。

  OpenLaszlo提供了两种创建与后端之间的持久连接的方法。一种方法要使用Lz(Laszlo 的缩写)标准库中提供的ConnectionManager API。但其文档明确说明了以下内容:

  “警告:这项特性是临时的。此特性用于容量有限的环境,能够用于开发,但我们不推荐使用此特性进行部署(不包括低容量、非任务关键型的部署)。若对使用此版本的持久连接的应用程序的健壮性有任何问题,请直接咨询Laszlo Systems。”

  或许目前这是一项实验技术,但在未来的OpenLaszlo版本中,它将得到证实。

  第二种方法与Flex相似,您要手动打开XML套接字连接,等待READ_DATA事件发生。清单6展示了实现方法。

  清单 6. 定义XMLSocket类
    

以下是引用片段:
<class name=”ClientSocket” extends=”node”>
 <attribute name=”host” />
 <attribute name=”port” />
 <XMLSocket name=’xml_socket’/>
 <handler name=”oninit”>
  // connect the socket here:
  xml_socket.connect(host,port);
 </handler>
 <handler name=’onData’ reference=’xml_socket’ args=’messageXML’>
 <![CDATA[
  ExternalInterface.call(‘handleServerMessageReceived’,messageXML);
 ]]>
 </method> 
</class>          

  (为简短起见,忽略了其他处理方法。在本文的下载部分中可获得完整的代码清单。)

  就是这样,创建一个套接字对象并连接此对象就是这样轻松。这一代码清单创建了一个名为ClientSocket的新类,随后声明了一个名为“xml_socket”的XML套接字对象。只要此套接字对象读取到来自服务器的数据,就会触发onData事件,该事件将由为onData定义的处理方法处理。最后,在onData处理方法中,调用Ajax应用程序中的外部JavaScript函数。此后的流程与Flex客户端相同。

  要创建ClientSocket对象,只需声明它即可:

  清单 7. 声明 ClientSocket
    

以下是引用片段:
<canvas>
 <ClientSocket id=’serverPushSocket’ host=’localhost’ port=’20340’/>
</canvas>       

  为ClientSocket触发了init事件时,将尝试连接指定主机和端口的后端。(请参见清单6中的oninit处理方法。)

  结束语

  这篇文章讨论了几种模拟服务器推送的方法,从纯轮询到实时服务器推送,文中说明了每种方法的优缺点。最后,我重点关注了能够提供最优服务器可伸缩性和实时服务器推送行为的方法。

  服务器推送并非适用于每一个应用程序。实际上,大多数应用程序都非常适合普通的请求/响应场景。其他一些应用程序使用轮询和类似的技术足以满足需求。只有那些服务器更新极为重要、客户端需要得到即时通知的重量级应用程序才需要本文所述技术。有必要再次强调,这种技术有两个主要的缺点:

  如果数据需要通过HTTPS传输,客户端套接字无法利用SSL加密工具。
 
  防火墙需要允许客户端套接字通过非标准端口(非80端口)连接到服务器。

  然而,市面上存在着大量开源库,您可利用它们轻松编写自定义的加密例程。类似地,配置防火墙也是轻而易举的,实际上,只需付出很少的代价,即可获得强大的实时服务器推送功能。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • 八个超实用的jQuery技巧攻略

    jQuery是JavaScript最好的库之一,主要用于制作动画、事件处理,支持Ajax及HTML脚本客户端。文中分享了8个超实用的jQuery代码技巧攻略,希望你会喜欢。

  • HTML5强大功能背后的安全陷阱

    尽管HTML5使网站的功能更为强大,但开发人员需充分利用其新的技术特征来提高网站的安全性,使用不当会带安全问题,你知道吗?

  • 前端页面开发之Node.js初学者指南

    Node.js是刚刚兴起的一个概念,你对它的了解有多少?Node.js的意义是什么,它是怎么发展起来的?Node.js的作用是怎样的呢?

  • JavaScript解析:让搜索引擎看到更真实的网页

    我们都知道期的搜索引擎没有相应的处理能力,会导致很多问题。引入JavaScript解析的目的,可以使搜索引擎可以更为清晰的了解用户实际打开该网页时看到的效果。