一.LoadVars篇
我之所以把XML也放在这里说,是因为XML和LoadVars数据交互的方式大体相同,就是传递时的数据内容有点不一样而已!
我现在列出在开发过程最常用的"用户密码验证"实例,加以说明!
复制代码 代码如下:
//=======================================================;
//Flash代码;
//=======================================================;
//定义LoadVars对象;
vardata_lv=newLoadVars();
//提交的用户名变量和参数值;
data_lv.username="kinglong";
//提交的密码变量和参数值;
data_lv.password="king";
//提交后返回结果;
data_lv.onLoad=function(success){
//success,数据提交是否成功;
//这个只是表示数据传输是否成功,并不是用户验证的结果;
if(success){
trace("数据提交成功!");
//result也是用户验证返回的实际结果!
if(this.result=="true"){
trace("yes");
}else{
trace("no");
}
}else{
trace("数据提交失败!");
}
}
//数据提交方法调用;
//第一参数就是提交的页面地址;
//第二参数就是返回结果对象(只要是LoadVars对象就可以了);
//第三参数就是提交方式(这个和html中form表单类似,分为"post"和"get"两种方式)
data_lv.sendAndLoad("http://www.klstudio.com/save.asp",data_lv,"post");
复制代码 代码如下:
//=======================================================;
//后台服务端页面处理及返回内容;
//=======================================================;
//接收flash提交过来的变量和接收一个页面提交过来的变量一致的;
Request("username")就是flash端username变量传过来的值"kinglong";
Request("password")就是flash端password变量传过来的值"kinglong";
....数据库验证.....
//如果用户验证通过
&result=true
//如果用户验证失败
&result=false
//整个页面返回内容就是上面那一行内容,&result对应用着flash端的result变量;
//如果是多个返回值的话,就是&result=xxx&result1=xxx这种形式就可以了;
如有不清楚的地方,你可查看flash帮助文档!
至于XML的方式,请对应地查看flash帮助文档就可以了!
LoadVars方式的优点:
1.flash代码实现起来简单,方便.
2.服务端接收页面和接收一个表单过来的数据一样处理,不需要专门的技术,所有服务端程序都可以实现!
LoadVars方式的缺点:
1.传递的变量不宜过多.
2.变量传递的值不宜过长.
3.变量传递值只能使用"字符串"这一种数据类型,数据类型单一.
4.数据返回值当中不能有"&"字符,因此比较复杂的返回值都需进行URL编码处理.
二、FlashRemoting
FlashRemoting这种数据接口是四个之中效率最高的!
其优点:
1.支持数据类型比较多(ConvertingfromapplicationserverdatatypestoActionScript);
2.传递数据量比较大;
3.运行效率是现有几个当中最高的;
4.对各种后台的支持也比较好;
5.其还有调试模块(NetConnectionDebugger)
其缺点:
1.需要flash端装FlashRemotingMXComponents(这个是免费提供的);
2.需要后台服务端装相应版本的FlashRemoting模块才可以使用,MM提供的模块有j2ee和.net两个版本是要收费的,好在网上还有两个开源的(OpenAMF,AMFPHP);
3.好像Remoting对虚拟主机的支持不太好(可以去google搜索一下,有没有解决方法).
复制代码 代码如下:
================================================================
Flash端代码说明:(我这里用as1.0版本为例,其他版本到MM站查找)
================================================================
//加载RemotingComponent代码,这个是必须的;
#include"NetServices.as"
//加载Remoting调试模块代码,这个是可选择的,用NetConnectionDebugger查看调试信息;
#include"NetDebug.as"
if(inited==null){
inited=true;
//设置默认网关;
NetServices.setDefaultGatewayUrl("http://localhost:8500/flashservices/gateway");
//建立网关连接;
gateway_conn=NetServices.createGatewayConnection();
//获取一个服务;
myService=gateway_conn.getService("myservice",this);
}
//定义调用方法的函数;
functiongetString(name){
//调用Remoting的getString方法;
myService.getString(name);
}
//定义返回结果的函数;
functiongetString_Result(result){
//result就为返回的结果;
trace(result);
}
//定义返回状态的函数,此为可选的;
functiongetString_Status(error){
trace("getString_Status");
trace(error.code);
trace(error.description);
trace(error.details);
}
//调用函数;
getString("kinglong");
复制代码 代码如下:
================================================================
服务端方法定义(我这里以ColdfusionComponent为例,其他版本请参考相应的资料)
================================================================
<->
<cfcomponentdisplayname="我的服务">
<->
<cffunctionname="getString"access="remote"returntype="string">
<cfargumentname="name"type="string"required="true">
<cfsetmyResult=arguments.name&",欢迎你!">
<cfreturnmyResult>
</cffunction>
</cfcomponent>
另附上FlashRemoting的在线帮助文件(FlashRemotingLiveDocs),MM网站上的Remoting相关的资料
三、WebService
个人觉得WebService的数据访问速度,仅次于Remoting,但WebService是一种通用型的接口,一般服务端技术都支持的!
WebService的优点:
1.WebService的接口支持比较广泛(Java,ASP.Net,PHP,Coldfusion-我下面举例用);
2.WebService是一个通用型的接口,所以服务端写的接口,不局限于Flash使用,其他程序也可以调用,"一举两得"!
3.WebService和Remoting一样,支持多种数据类型!
4.今天还发现FMS除了支持Remoting接口,也支持WebService接口了:)
WebService的缺点:
Flash客户端到是没有什么问题,Flash的开发工具就自带了(WebServiceConnector组件),但服务端虽说大多都支持这个接口技术,但除了Coldfusion生成WebService方便外,其他的实现都挺复杂的!
复制代码 代码如下:
//=======================================;
//Flash客户端代码;
//对于代码不是很熟悉的可以直接使用WebServiceConnector组件,进行设置设置就可以了。
//我这里主要是写用代码来调用WebService方法。
//当然这个前提是你要把WebServiceConnector组件先放到库里,否则类就无法引用了。
//=======================================;
stop();
//引用WebService类;
importmx.services.WebService;
//定义WebService的路径;
varws_url:String=http://localhost:8500/klstudio/myservice.cfc?wsdl;
//定义WebService对象;
varws:WebService=newWebService(ws_url);
//调用WebService方法;
varcallObject=ws.getSting("kinglong");
//设置返回结果对象;
callObject.onResult=function(result){
trace("result:"+result);
}
//如果调用错误返回信息(这个是可选的);
callObject.onFault=function(fault){
trace("fault:"+fault.faultstring);
}
注意:如果返回结果是一个数据集的话,那每个字段名都要用大写,不管你的服务端是否大写!
复制代码 代码如下:
================================================================
服务端方法定义(我这里仍以ColdfusionComponent为例,其他版本请参考上面提供的连接)
================================================================
<->
<cfcomponentdisplayname="我的服务">
<->
<cffunctionname="getString"access="remote"returntype="string">
<cfargumentname="name"type="string"required="true">
<cfsetmyResult=arguments.name&",欢迎你!">
<cfreturnmyResult>
</cffunction>
</cfcomponent>
调用的时候,只要在cfc路径后面加"?wsdl"就可以了,方便吧!:)
四、XMLSocket
XMLSocket主要用于与服务端进行即时通信,目前的应用领域主要是Flash文本聊天和Flash在线游戏等方面。
XMLSocket的优点:
1、能和服务端即时通信;
2、FlashPlayer5.0以上的版本内置类,不需另装组件或插件;
3、因为XMLSocket就是相当于一个Socket客户端,所以一般的中间件都支持的(如java,.Net等)
XMLSocket的缺点:
1、XMLSocket只能传字符串或xml格式的文本,数据类型单一;
2、XMLSocket服务端自行开发的话,需要对Socket技术比较了解才行,好在网上有现成的服务端软件(商业的XMLSocketServer有Unity、Fortress;开源的XMLSocketServer有OreganoMultiuserServer);
3、还有就是XMLSocket的80端口与flash安全策略问题。(网上有一个解决方法,不知是否可行,请自行验证)
复制代码 代码如下:
//=======================================;
//Flash客户端(以Flash文本聊天为例);
//=======================================;
varparamObj:Object=newObject();
//命令分隔符;
paramObj.CommandDelimiters="-@@##@@-";
//用户列表分隔符;
paramObj.PeopleDelimiters="-@#@-";
//建立XMLSocket对象;
varsocket:XMLSocket=newXMLSocket();
//连接状态事件;
socket.onConnect=function(success){
trace("socket.onConnect:"+success);
if(!success){
trace("服务器连接失败,请检查网络状态!");
}
};
//关闭事件;
socket.onClose=function(){
trace("服务端已关闭!");
logoutChat();
};
//数据通信事件;
socket.onData=function(src){
//trace("socket.onData:"+src);
doCommand(getCmdArrayByMsg(trim(src)));
};
//用户登录;
functionloginChat():Void{
//连接Socket服务端;
socket.connect(“localhost”,“8888”);
sendSocket("INFO"+paramObj.CommandDelimiters+msg);
}
//用户注销;
functionlogoutChat(b:Boolean):Void{
sendSocket("QUIT");
}
//显示聊天信息;
functionshowChat(msg:String):Void{
trace(“聊天信息:”+msg);
}
//发送聊天信息;
functionsendChat(msg:String):Void{
sendSocket("MSG"+paramObj.CommandDelimiters+msg+paramObj.CommandDelimiters+msg);
}
//向服务端发送信息;
functionsendSocket(msg:String):Void{
socket.send(msg+"r");
}
//处理服务端返回信息;
functiongetCmdArrayByMsg(msg:String):Array{
if(msg.charCodeAt(0)==13&&msg.charCodeAt(1)==10){
msg=msg.substr(2);
}
returnmsg.split(paramObj.CommandDelimiters);
}
functiondoCommand(arr:Array):Void{
switch(arr[0]){
case"MSG":
showChat(arr[1]);
break;
case"TAKEN":
trace("你的登录名已经有了,请重新换一个登录名!");
break;
case"PEOPLE":
doPeople(arr[1]);
break;
}
}
//显示在线用户列表;
functiondoPeople(msg:String):Void{
varpeople_arr:Array=msg.split(paramObj.PeopleDelimiters);
trace(people_arr);
//上面与XMLSocket有关的主要代码,显示方面自己添加相关组件就行了!
//有一个注意点,在flash向服务端发送的命令的最后一定要加上“r”,否则服务端无法收到消息(我的服务端是用Java开发的)
程序代码
//=======================================;
//服务端代码(我用java开发的,其他版本自行研究);
//ChatServer.java
//=======================================;
packagecom.klstudio.socket.chat;
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.util.Vector;
//importcom.klstudio.util.Logger;
/**
*@authorkinglong
*
*TODO要更改此生成的类型注释的模板,请转至窗口-首选项-Java-代码样式-代码模板
*/
publicclassChatServer{
//privateLoggerlogger;
privatestaticVectorclients=newVector();
privatestaticServerSocketserver=null;
privatestaticSocketsocket=null;
publicstaticStringCommandDelimiters="-@@##@@-";
publicstaticStringPeopleDelimiters="-@#@-";
publicChatServer(){
}
publicstaticvoidnotifyRoom(){
StringBufferpeople=newStringBuffer("PEOPLE"+CommandDelimiters+"所有的人");
for(inti=0;i<clients.size();i++){
Clientclient=(Client)clients.elementAt(i);
people.append(PeopleDelimiters+client.getClientName());
}
sendClients(people);
}
publicstaticbooleancheckName(ClientnewClient){
for(inti=0;i<clients.size();i++){
Clientclient=(Client)clients.elementAt(i);
if(client!=newClient&&client.getClientName().equals(newClient.getClientName())){
returnfalse;
}
}
returntrue;
}
publicstaticvoidcloseAll(){
while(clients.size()>0){
Clientclient=(Client)clients.firstElement();
try{
client.getClientSocket().close();
}catch(IOExceptione){
//TODO自动生成catch块
//Loggerlogger=newLogger(System.out);
//logger.log("错误-"+e.toString());
}finally{
clients.removeElement(client);
}
}
}
publicstaticsynchronizedvoiddisconnect(Clientclient){
client.send(newStringBuffer("QUIT"));
try{
client.getClientSocket().close();
}catch(IOExceptione){
//TODO自动生成catch块
//Loggerlogger=newLogger(System.out);
//logger.log("错误-"+e.toString());
}finally{
clients.removeElement(client);
}
}
publicstaticsynchronizedvoidsendClients(StringBuffersb){
for(inti=0;i<clients.size();i++){
Clientclient=(Client)clients.elementAt(i);
client.send(sb);
}
}
publicstaticsynchronizedvoidsendClients(StringBuffersb,StringownerName,StringtoName){
for(inti=0;i<clients.size();i++){
Clientclient=(Client)clients.elementAt(i);
if(toName.equals(client.getClientName())||toName.equals("所有的人")||ownerName.equals(client.getClientName())){
client.send(sb);
}
}
}
publicstaticsynchronizedvoidsendClients(ClientownerClient){
for(inti=0;i<clients.size();i++){
Clientclient=(Client)clients.elementAt(i);
if(client.getClientName().equals(ownerClient.getClientName())){
client.send(newStringBuffer("MSG"+CommandDelimiters+"系统信息>欢迎你进入!"));
}else{
client.send(newStringBuffer("MSG"+CommandDelimiters+"系统信息>["+ownerClient.getClientName()+"]用户进入!"));
}
}
}
publicstaticvoidmain(String[]args){
intport=8888;
if(args.length>0){
port=Integer.parseInt(args[0]);
}
//Loggerlogger=newLogger(System.out);
//logger.log("信息-ChatServer["+port+"]服务正在启动...");
try{
server=newServerSocket(port);
}catch(IOExceptione){
//TODO自动生成catch块
//logger.log("错误-"+e.toString());
}
while(true){
if(clients.size()<5){
try{
socket=server.accept();
if(socket!=null){
//logger.log("信息-"+socket.toString()+"连接");
}
}catch(IOExceptione){
//TODO自动生成catch块
//logger.log("错误-"+e.toString());
}
inti=0;
do{
Clientclient=newClient(socket);
if(client.getClientName()!=null){
clients.addElement(client);
if(checkName(client)){
//logger.log("信息-"+"目前有["+clients.size()+"]个用户已连接");
sendClients(client);
client.start();
notifyRoom();
}else{
client.send(newStringBuffer("TAKEN"));
disconnect(client);
}
i++;
}
break;
}while(i<clients.size());
}else{
try{
Thread.sleep(200);
}catch(InterruptedExceptione){
//TODO自动生成catch块
//logger.log("错误-"+e.toString());
}
}
}
}
}
复制代码 代码如下:
//=======================================;
//Client.java
//=======================================;
/*
*创建日期2005-10-10
*
*TODO要更改此生成的文件的模板,请转至
*窗口-首选项-Java-代码样式-代码模板
*/
packagecom.klstudio.socket.chat;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.PrintStream;
importjava.net.Socket;
//importcom.klstudio.util.Logger;
/**
*@authorkinglong
*
*TODO要更改此生成的类型注释的模板,请转至窗口-首选项-Java-代码样式-代码模板
*/
publicclassClientextendsThread{
privateSocketclientSocket;
privateStringclientName;
privateStringclientIp;
privateBufferedReaderbr;
privatePrintStreamps;
//privateLoggerlogger;
privateChatServerserver;
publicClient(Socketsocket){
//this.logger=newLogger(System.out);
this.clientSocket=socket;
try{
this.br=newBufferedReader(newInputStreamReader(socket.getInputStream(),"utf-8"));
this.ps=newPrintStream(socket.getOutputStream(),true,"utf-8");
Stringinfo=this.br.readLine();
if(info!=null){
String[]info_arr=info.split(ChatServer.CommandDelimiters);
if(info_arr.length>1){
this.clientName=info_arr[1];
}
this.clientIp=socket.getRemoteSocketAddress().toString();
}else{
socket.close();
}
}catch(IOExceptione){
//TODO自动生成catch块
//this.logger.log("错误-"+e.toString());
}
}
/**
*@return返回ip。
*/
publicStringgetClientIp(){
returnclientIp;
}
/**
*@return返回name。
*/
publicStringgetClientName(){
returnclientName;
}
/**
*@return返回socket。
*/
publicSocketgetClientSocket(){
returnclientSocket;
}
publicvoidsend(StringBuffermsg){
this.ps.println(msg.toString()+"");
//this.ps.flush();
}
publicvoidrun(){
while(true){
Stringline=null;
try{
line=this.br.readLine();
}catch(IOExceptione){
//TODO自动生成catch块
//this.logger.log("错误-"+e.toString());
ChatServer.disconnect(this);
ChatServer.notifyRoom();
return;
}
if(line==null){
//this.logger.log("信息-["+this.clientName+this.clientIp+"]用户离开!");
ChatServer.disconnect(this);
ChatServer.notifyRoom();
if(this.clientName!=null){
ChatServer.sendClients(newStringBuffer("MSG"+ChatServer.CommandDelimiters+"系统信息>["+this.clientName+"]用户离开!"));
}
return;
}
//this.logger.log("信息-"+line);
String[]cmd_arr=line.split(ChatServer.CommandDelimiters);
Stringkeyword=cmd_arr[0];
keyword=keyword.substring(1);
if(keyword.equals("MSG")){
StringBuffermsg=newStringBuffer("MSG"+ChatServer.CommandDelimiters);
msg.append(this.clientName+">");
msg.append(cmd_arr[1]);
ChatServer.sendClients(msg,this.clientName,cmd_arr[2]);
}elseif(keyword.equals("QUIT")){
//this.logger.log("信息-["+this.clientName+this.clientIp+"]用户离开!");
ChatServer.disconnect(this);
ChatServer.notifyRoom();
ChatServer.sendClients(newStringBuffer("MSG"+ChatServer.CommandDelimiters+"系统信息>["+this.clientName+"]用户离开!"));
this.stop();
return;
}
}
}
}
//注意,服务端向客户端发送的信息,必需以””,空字符结尾,否则客户端也无法接收到信息!
五、FlashCom(FMS)
FlashCom(FMS)主要用于与服务端进行流媒体通信,目前应用领域就是Flash流媒体播放,Flash在线直播,Flash视频音频聊天,Flash视频会议,Flash在线游戏等。
FlashCom的运行环境(FMS的运行环境):
1、Windows操作系统:Windows2000Server或者WindowsNT4.0Server(sp6);
2、Linux操作系统:RedHatLinux7.3或者8.0;
3、服务器的CPU是PentiumIII500MHz或者更高(推荐值是双个Pentium4CPU);
4、服务器的内存是256MRAM或者更高(推荐值是512M)。
FlashCom(FMS)的优点:
1、能够实现即时视频音频通信(当然它也支持文本通信的);
2、能够流媒体同步播放(也叫在线直播);
3、能够通过FlashPlayer(6.0以上版本)录制视频音频,无需其他客户端;
4、能够实现客户端实现之间的控制(如会议主持人权限)。
FlashCom(FMS)的缺点:
1、FlashCom(FMS)服务端软件是MM公司的产品,需要花银子去买的(一笔不小的投入),好在现在有一个正在完善中的开源项目——RED5;
2、由于是流媒体服务端软件,所以对服务器的带宽,内存,以及CPU也是很高的要求的(上面已经作说明了);
3、同时在线视频通信的人数不能太多。
程序代码
//=======================================;
//Flash客户端(以简单的在线录制视频为例)
//=======================================;
stop();
varnc:NetConnection=newNetConnection();
varns:NetStream;
varcam:Camera=Camera.get();
varmic:Microphone=Microphone.get();
//预览本地摄像头视频;
video_box.attachVideo(cam);
//初始化NetStream;
functioninitNetStream():Void{
ns=newNetStream(nc);
//设置2秒的缓冲时间;
ns.setBufferTime(2);
//使用NetStream加载视频和音频对象;
ns.attachVideo(cam);
ns.attachAudio(mic);
//NetStream状态信息;
ns.onStatus=function(info:Object){
trace("ns.onStatus:"+info.code);
};
}
//录制视频音频;
functionrecordStream(){
ns.publish("kinglong","record");
}
//停止录制;
functionstopStream(){
ns.close();
}
//删除视频音频文件;
functiondeleteStream(){
nc.call("clearStream",null,"kinglong");
}
//NetConnection状态信息;
nc.onStatus=function(info:Object){
trace("nc.onStatus:"+info.code);
switch(info.code){
case"NetConnection.Connect.Success":
initNetStream();
break;
}
};
//连接FlashCom服务器
nc.connect("rtmp:/"+"recordstream");
程序代码
//=======================================;
//FlashCom(FMS)服务端代码
//将下列代码存成main.asc文件(此文件名固定),在FlashCom的applications目录下建立一个recordstream目录(对应着客户端的”recodstream”),并将main.asc放在这个目录中。
//=======================================;
application.onAppStart=function(){
}
application.onAppStop=function(){
}
application.onConnect=function(client){
application.acceptConnection(client);
}
application.onDisconnect=function(client){
}
//=======================================;
//获取flv文件时间长度;
functiongetStreamLength(name){
returnStream.length(name);;
}
//=======================================;
//删除flv文件;
functionclearStream(name){
trace("clearStream("+name+");");
varstream=Stream.get(name);
returnstream.clear();
}
//=======================================;
//设置Client.prototype;
//=======================================;
Client.prototype.getStreamLength=getStreamLength;
Client.prototype.clearStream=clearStream;
补上FMS官方中文网站相关资料地址:
http://www.macromedia.com/cn/software/flashmediaserver/productinfo/pricing/