首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

在 Ajax 应用程序中实现实时数据推送 -3 基于套接字的 RIA 技术

在 Ajax 应用程序中实现实时数据推送 -3 基于套接字的 RIA 技术

基于套接字的 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. 创建服务器套接字
1
2
3
4
5
6
7
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 客户端策略文件
1
2
3
4
5
6
<?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. 发送策略文件响应
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 打开客户端
1
2
3
4
5
6
7
8
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 代码
1
2
3
4
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 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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
1
2
3
<canvas>
    <ClientSocket id='serverPushSocket' host='localhost' port='20340'/>
</canvas>




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