收藏本站 收藏本站
积木网首页 - 软件测试 - 常用手册 - 站长工具 - 技术社区
积木学院 > 网页设计 > Flash > 正文

利用套接字机制实现Flash与数据库连接

来源:互联摘选 日期:2005-06-28 19:16
  无论对于Java开发者还是.NET开发者来说,在Flash中创建一个数据库连接都不是件简单的事情。由于解决这一问题需要费不少的周折,所以本文中我们通过建立一个XMLSocket类来帮助实现这一技术。

  一、 简介

  对于一位具有传统型客户-服务器背景的开发人员来说,转入到ActionScript开发并把Flash连接到一个数据库肯定需要费不少的周折。在.NET或Java世界中,通过直接从应用程序中调用数据库,你仅需要打开一个到数据库的连接并且执行数据库操作即可;而在Flash情况下事情并不这么简单。在本文中,我将向你介绍解决这一问题的办法。

  即使在一个非传统型开发环境例如Flash中,进行数据库连接都是非常必要的。例如,你可能想要存储一个游戏中的高分,或任何需要在会话间持续存储的用户信息。而且,对于灵活的数据库连接的需求也正在增长,因为现在已经有越来越多的人基于Flash方案构建丰富的互联网应用程序。

  归纳来看,共有三种方式可以使一个Flash应用程序连接到数据库上:

  · 使用XMLConnector组件;

  · 使用XML与CGI的结合;

  · 使用XMLSocket类。

  必须清醒地认识到,没有直接的把Flash连接到一个数据库的方法;必须有一个应用程序来担当Flash和数据库的中介。上面描述的每个方法都使用了这种机制-每一种在实现方式上稍有不同且包含不同的Flash特征。

  第一种方法在Flash帮助中有良好的说明,在此不再多言。

  第二种方法使用在Flash一端的XML类与在服务器端的一个CGI应用程序的结合,它比较适合于网络应用不存在问题的情况下。这种方法使用一个POST HTTP请求来连接到应用程序服务器。有关此更好的解释,请参考Flash帮助资料(ActionScript参考指南>用外部数据工作>从远程源中发送和装载变量>使用XML类)。

  第三个方法(本文将集中讨论),因为某些原因,具有极少的文档可参考。然而,从一个程序员的角度来看,它却是提供最多的控制的方法。对于一位非Flash程序员来说,这也是最熟悉的数据库交互的比喻。根据Flash帮助信息,"XMLSocket…维持一打开的到服务器的连接,它允许服务器可以在没有一来自客户方请求的情况下立即发送到来的消息。"

  为了展示XMLSocket的使用方法,我构建了一个简单的应用程序:一个Flash数据库前端(见图1)。这对于使用查询工具的用户是非常熟悉的,因为它实现了常用设计:屏幕提供了认证信息字段,还有一个字段用于输入要被传递到数据库的SQL命令。虽然不可能任何人都会用Flash构建一个完整功能的数据库查询工具,但是在本示例中所用的方法可以为实现任何特定的需要而加以定制。

利用套接字机制实现Flash与数据库连接
图1.连接GUI:该图像显示一个在Flash中构建的数据库前端。


  二、 基本原则

  实际的数据库操作是通过一个后端Java应用程序(在Flash帮助中称为"daemon")实现的,它经由JDBC(Java数据库连接)连接到数据库。我选择了Java是因为它跨平台并且还因为它的语法易于为ActionScript开发者们所理解。一个基于.NET的后端在概念上看起来与此相似。
就算你不知道Java,如果你有一些使用ActionScript的经验,那么你应该毫无问题地理解本文。如果你是一个Java或.NET程序员而没有深厚的Flash经验,那么我也希望本文能提供一些信息来帮助你使用熟悉的概念构建你的数据库连接框架。

  注意 为试验本文程序你需要:

  · Flash MX 2004 或Flash 8(专业版)

  · Java IDE(我使用的是Eclipse 3.0)

  · Microsoft SQL Server 2000 driver for JDBC

  · SQL Server 2000

  Java后端和Flash前端将通过套接字通讯。在Java中,套接字分为服务器套接字(听取并响应到来的请求)和客户套接字(把请求发送到服务器套接字)两大类。有关Java套接字的完整讨论已经超出本文的范围,因此如果你对它们不熟悉的话,请参考网上其它资源;对于本文目的来说,把套接字当作是两个应用程序之间通过网络的数字连接已经足够了。

  请注意,Flash仅仅支持"客户套接字"-它能连接到一个服务器,但是不担当到其它客户套接字的服务器,并且是在XMLSocket类中实现的。

  XMLSocket有一些限制:

  · 仅有可能连接到大于或等于1024的TCP端口;

  · 默认情况下,安全约束会禁止连接到一个运行于不同域上的服务器应用程序(而不是SWF文件)。这个默认行为可以通过重载来解决,详见Flash参考文档。

  为使得通讯具有意义,这两个应用程序必须使用一互相都能理解的协议(在本文情况中,我们基于XML):一个以0为终结符的XML文件被Flash发送到后端应用程序并且执行一定操作(在我们的情况中是数据库存取)。

  在我们的查询工具情况下,在数据库上执行一个命令是一个两步的过程:首先,使用提供的凭证连接到数据库。然后,如果连接成功,发送和执行该命令(作为SQL语句)。由于我构建的查询应用程序具有的特点(一个会话可能包括许多事务)以及我想在Java和Flash之间构建一个更复杂一些的通讯协议,所以我选择了这种两步过程。然而,有可能把认证和执行结合到一个步骤中-发送到Java应用程序的来自Flash的消息只需简单地包括认证信息和命令;然后,Java后端将返回该SQL命令的输出(或,在连接或执行失败情况下,对应一条错误消息)。

  为了实现到一个SQL Server数据库的认证,要求提供下列信息:

  · 数据库服务器的IP地址;

  · 数据库登录和口令;

  · 数据库名;

  · 该Java应用程序的IP地址或DNS名(它可以与数据库IP名字相同,也可以不同)。

  一旦该Java应用程序检测到一个连接尝试,它将尽量分析它所收到的XML消息。如果它是一条'open connection'消息,该应用程序将从数据库服务器中提取IP地址、登录、口令和数据库名;它将尝试打开一个到数据库的JDBC连接;如果成功,它将把一条XML消息和唯一的连接句柄返回到Flash前端。它还将把认证信息和连接数字(一个"句柄")添加到一内部的连接集合上。

  跟随一个成功的连接,该前端发送一SQL命令,它还在消息中包含了连接句柄。一旦接收一个SQL命令,后端将提取属于该连接句柄的认证信息并且使用它把该命令发送到数据库。

  前端所发送的打开一个连接的XML消息具有下列格式:

<flashLogon>
<IPAddr>127.0.0.1</IPAddr>
<Login>sa</Login>
<Password>admin_password</Password>
<Database>user_database</Database>
</flashLogon>

  请注意,这里的前端有两个IP地址域:一个持有IP地址或Java应用程序正在其上运行(端口号1024)的服务器的DNS名,而另外一个持有数据库服务器的IP地址;上面的<IPAddr>引用了数据库服务器。

  处理一个SQL命令的消息有下列格式:

<flashCommand>
<Command>SELECT * FROM Table1</Command>
<Connection>1</Connection>
</flashCommand>

  如果连接是成功的,Java服务器应用程序将返回下列消息:

<Connection>
<HConnection>1</HConnection>
</Return>

  处理一个命令后,返回一条类似于下面的消息:

<Return>
120
</Return>

  然而,这条消息也可能更复杂些,例如:

<Return>
Michaels,Rich,1200,10962 Acacia St
King,Mary,98012,11128 Maryland Ave
</Return>

  它还有可能包含一条错误消息,例如:

<Return>
SQL Error 101 Table does not exist.
</Return>

  三、 构建前端

  现在,我们分析一下本文源码中的SocketGUI.fla文件。在Frame0中,我装载了后台代码文件(GlobalFrame0.as)。其中,Frame1包含GUI元素。在Frame1中的所有的按钮事件处理器简单地参考在GlobalFrame0.as中的方法。

  Connect函数处理针对'Connect'按钮的点击功能。我使用XMLSocket的connect函数并使用端口1024(这可能是大于或等于1024的任何16位数)来试图打开一个到Java应用程序的连接。

  使用XMLSocket打开一个连接分两步:首先,调用connect方法;然后Flash调用onConnect事件处理器以通知该应用程序试图连接的成功或失败;在这个处理器中,你必须加入代码来处理试图打开该连接的结果。

  为使连接完全成功,在我们的示例应用程序中,必须确保到Java应用程序的XMLSocket.connect调用成功执行,并且数据库认证也要成功执行。如果这两个条件都满足,那么该Java应用程序将返回一个XML编码的连接数字,并把它存储在HConnection变量中。当Flash收到来自服务器的消息时,XMLSocket的onData事件将激发。当然,可能收到不同的响应消息:一个成功的连接将收到一个连接数字,而一个数据库命令将收到一条来自数据库的消息。ParseReturn函数决定收到的响应的种类并且根据这一响应继续执行下去。

  如果连接成功,现在用户就能把一条命令发送到数据库;这一功能是在SendCommand函数中实现的,它就象调用XMLSocket.send一样简单。

  Connect和SendCommand都需要适当格式化消息以便Java应用程序理解它们(上面描述的XML格式)。XMLCreateLogon和XMLCreateCommand正是完成此任务。你将注意到,每个消息需要被一个换行符字符终止('\n'),否则Java服务器套接字不会接收此消息。

  有关Flash编码所剩下的唯一的事情是断开功能;为了实现断开连接,你可以按下'Disconnect'按钮或在命令行上发送一个'disconnect'消息。所有的功能(基本上是从集合中删除数据库认证和句柄)在服务器应用程序中实现;在Flash中,我仅重置了连接句柄。

  四、 构建后端

  Java后端应用程序有两部分:一个'listener'类(称作oSckSrv),它使用Java套接字来接收来自Flash的XML命令和一个'executor'类(称作dbConn),它实现实际的数据库通讯功能。

  该Java应用程序的核心是一个无限循环(参考在oSckSrv.java文件中的主循环部分)。它简单地在端口1024上等待接收一连接请求,一旦收到连接请求,立即使用一个流读取器来读取该XML消息。在试用了各种读取器后,我发现BufferedReader Java类最适当于接收文本(XML)字符串。然后,parseReceivedXML函数被调用以解释该消息。这个函数使用文档对象模型API来分析从Flash收到的XML文档。

  如果收到一'logon'消息,那么dbConn类的getConnection函数被调用以试图打开到数据库的连接。如果收到一'command'消息,那么程序代码将分析是否该XML消息嵌入一个有效的(现有)连接句柄。如果该句柄有效,dbConn用于传送从Flash中收到的SQL消息。

  dbConn类负责实现实际的数据库工作。如果你对JDBC熟悉,或有其它协议的使用经验,例如ODBC甚至ADO,那么这部分代码就非常容易理解。Connect函数使用认证参数打开一到数据库的连接,但是真正有趣的函数是Execute,它使用接收自Flash前端的SQL命令串,并且把它传递给数据库服务器的引擎来以任何方式处理它。显然,Flash和Java都不知道发送给数据库的消息;仅由数据库服务器来理解它!

  Execute函数把来自于数据库服务器的XML格式的输出返回到调用者(oSckSrv),由它再把该输出传送回前端。该消息必须以一个'\0'终止,以便Flash的XMLSocket正确接收它。

  在我的dbConn编程中,我使用了Microsoft SQL Server数据库。然而,你可以很容易地看到,该Java应用程序不必直接连接到一个数据库,一个数据库服务器或一个数据库平台。如果你想要连接到除SQL Server以外的数据库服务器,你需要修改该代码以加载适当的JDBC驱动程序并且通过前端提供适当的连接参数。你还有可能需要在Flash前端添加一个'database type'参数来帮助服务器代码决定在运行时刻装载哪个驱动程序。

  我必须承认,为了简单一些,我做了点"小动作"。你会在ActionScript代码中注意到,在调用XMLSocket的send方法之前,我再次打开该连接。我本来可以让该连接打开并准备接收更多的请求(经由ino缓冲读取器);然而,ServerSocket类的accept方法正被阻塞,这意味着在允许进一步的处理前它将等待另一个连接请求;同时,如果我等待ino.readLine接收来自于一个已经连接的客户的更多的命令,那么该Java应用程序就不会服务来自于其他客户的连接请求。我现在使用的编程方式是,一旦收到一个连接请求,该请求即被服务并且由服务器关上该TCP/IP连接(这正是一旦该Flash应用程序连接或把一个命令提交到该Java应用程序就显示'Connection closed'消息的原因);然后,该应用程序返回以等待另一个连接请求。

  在Java应用程序中的实际开发中的套接字读和写一般是在一个单独的线程中执行的;一旦收到一个连接请求并且一个到客户的连接被打开,该连接的处理应该被独立于main线程(现在它正在等待另一个连接的打开)执行。这可能会增加Java编码的复杂性;因此在本文中,我在ActionScript中使用了"欺骗"方式并且打开/关闭该连接,而避开了处理Java多线程问题。然而,必须注意到在实际应用程序中,为了减少与打开TCP/IP连接相关的网络性能问题,有可能需要实现一种全双工连接的会话。

  然而,最大的挑战还在于,处理各种不加限制的输出(这可能来自于从前端提交的查询结果)。一真正的查询工具将使用一种很复杂的协议来格式化查询输出(例如,SQL Server使用一种名为Tabular数据流的内部协议,它向客户"描述"由服务器发送的响应),这已经超出了本文所及的范围。为此,我仅实现一个简单的返回消息-每个记录的第一列以<Return>标签封尾。这个响应可能是一个数据库记录集,一个返回代码或一条消息;具体应视发送的SQL命令而定。一实际的应用程序将需要使用一组复杂的XML标签来嵌入响应并且在前端实现同等复杂的逻辑以解码这条消息。

  然而,一个实践中的Flash应用程序,可能不希望处理各种各样的数据库服务器响应。例如,你可能仅仅需要得到一个用户的最高分和一些用户选择。在这种情况中建立一种有意义的协议将相当简单。

  五、 限制

  实现本文示例模型的最大的挑战是,需要客户应用程序了解由服务器应用程序从数据库返回的元数据(结构)信息。然而,典型情形下将包含一个Flash应用程序-它仅提交到数据库的一有限数量的查询并且得到一有限数量的响应,这样可以使得ParseReturn函数的大小和复杂性适中。事实上,在本文开始提到的另一些数据库连接方法确实要求程序员定义要被交换的消息的XML模式,因此不能回避描述要被接收的数据。

  通讯容量是另外一个限制因素:一个强壮的需要回答很多客户调用的服务器应用程序可能需要使用多线程、连接池及其它高级技术。
另外,在Flash应用程序和Java应用程序之间的通讯安全很重要的:我的示例程序中发送了有可能被"偷窥"的未加密数据。一个实际的应用程序在经由套接字发送数据之前需要对之进行加密。

  六、 建立环境

  你可以把该Java应用程序安装在与数据库服务器相同或不同的机器上。为了启动该Java应用程序,你必须在DOS下执行这个命令(见本文所附源代码中的launch.bat文件):

set CLASSPATH=.;%CLASSPATH%;C:/Program Files/Microsoft SQL Server 2000 Driver for
JDBC/lib/mssqlserver.jar;C:/Program Files/Microsoft SQL Server 2000 Driver for JDBC
/lib/msutil.jar;C:/Program Files/Microsoft SQL Server 2000 Driver for JDBC/lib/msbase.jar;
java oSckSvr

  注意 这个命令的重点部分是MS SQL Server到JDBC驱动程序的路径。

  对于有很少Java经验的开发者来说,建立开发环境可能有点小困难。我使用了显示在图2中的目录结构。我建立我的Eclipse环境从而把Java二进制文件复制到\bin子目录下,如图3所示。图4和5展示了该应用程序建立一个到数据库的连接并接收一个响应。

利用套接字机制实现Flash与数据库连接
图2.Java应用程序目录结构:这个屏幕快照显示了作者的源码目录结构。
利用套接字机制实现Flash与数据库连接
图3.Java应用程序目录结构:这个屏幕快照显示了作者的在Eclipse中的二进制文件和启动程序文件(launcher)的目录结构。
  作者注:你可以从微软的站点下载相应于SQL Server的JDBC驱动程序。

利用套接字机制实现Flash与数据库连接
图4.连接到数据库:这个快照中显示的是正在建立一个到SQL Server的连接。
利用套接字机制实现Flash与数据库连接
图5.查询和响应:SQL Server收到来自图4的查询并且发送它的响应。
  为了允许Flash客户下载来自Java应用程序的响应(如果这两个程序不是位于同一个域上的话),在web服务器上需要有一个跨域的XML策略文件。更多细节,请参考Flash帮助。

  总之,尽管与一个数据库的典型通讯在Flash中并不象在其它开发环境中那样直接,但是它也可以借助于一个"中介"(例如,使用JDBC或ADO协议来访问数据库的应用程序)来实现。

推荐阅读

 

热点信息

 
强悍的草根IT技术社区,这里应该有您想要的! 友情链接:b2b电子商务
Copyright © 2010 Gimoo.Net. All Rights Rreserved  京ICP备05050695号