Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)
Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)
发布时间:2016-12-28 来源:查字典编辑
摘要:FluorineFx所提供的远程共享对象(RemoteSharedObjects)和FMS的共享对象的功能是一样,对于熟悉FMS开发的朋友来...

FluorineFx所提供的远程共享对象(Remote Shared Objects)和FMS的共享对象的功能是一样,对于熟悉FMS开发的朋友来说,学习FluorineFx的远程共享对象是非常简单的。

共享对象可以在服务器端创建,也可以在客户端创建。在客户端创建共享对象的方法和使用FMS开发是一样的,创建一个 NetConnection对象,通过该对象的connect()方法连接到服务器,然后通过SharedObject.getRemote()方法就可以在客户端创建一个远程共享对象。如下实例代码:

privatefunctionconnectionServer():void

{

varnc:NetConnection=newNetConnection();

nc.connect("rtmp://localhost:1617/SOAPP","username","password")

nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);

nc.client=this;

}

privatefunctiononStatusHandler(event:NetStatusEvent):void

{

if(event.info.code=="NetConnectin.Connect.Success")

{

createSharedObject();

}

}

privatefunctioncreateSharedObject():void

{

varso:SharedObject=SharedObject.getRemote("OnLineUsers",nc.uri,false);

so.addEventListener(SyncEvent.SYNC,onSyncHandler);

so.connect(this.nc);

so.client=this;

}

privatefunctiononSyncHandler(event:SyncEvent):void

{

//Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)1..doother

}

在FluorineFx的服务器端创建远程共享对象和FMS有很大的区别,FluorineFx的 ISharedObjectService接口提供了专门用于创建远程共享对象的方法 CreateSharedObject(),ApplicationAdapter实现了此接口方法。定义如下:

publicboolCreateSharedObject(IScopescope,stringname,boolpersistent)

{

ISharedObjectServiceservice=(ISharedObjectService)ScopeUtils.GetScopeService(scope,typeof(ISharedObjectService));

returnservice.CreateSharedObject(scope,name,persistent);

}

如果要在服务器端创建远程共享对象,直接调用ApplicationAdapter类中的CreateSharedObject()方法就可以。如下在FluorineFx服务器端创建远程共享对象的代码块:

ISharedObjectusers_so=GetSharedObject(connection.Scope,"OnLineUsers");

if(users_so==null)

{

//创建共享对象

CreateSharedObject(connection.Scope,"OnLineUsers",false);

users_so=GetSharedObject(connection.Scope,"OnLineUsers");

}

要想更新共享对象里的数据客户端还是使用setProperty()方法,而FluorineFx的服务器更新共享对象的方法则与 FMS不一样,使用的是FluorineFx.Messaging.Api.IAttributeStore接口提供的SetAttribute()和 RemoveAttribute()方法来更新共享对象里的数据。

陆续介绍了这么多,下面通过一个案例来看看该这么去应用远程共享对象。比如做IM、视频聊天、视频会议等及时通信类型的应用中,用户上线下线的频率非常高,这时候我们就可以使用远程共享对象去做在线用户的数据同步。

首先建立FluorineFx服务库,并建立一个应用类继承于ApplicationAdapter,通过重写ApplicationAdapter的相关方法来实现应用程序的不同需求,详细如下代码块:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingFluorineFx.Messaging.Adapter;

usingFluorineFx;

usingFluorineFx.Messaging.Api;

usingSystem.Diagnostics;

usingFluorineFx.Messaging.Api.SO;

usingFluorineFx.Exceptions;

usingFluorineFx.Context;

usingFluorineFx.Messaging.Api.Service;

usingSystem.Collections;

usingFx.Adapter.DTO;

namespaceFx.Adapter

{

///<summary>

///自定义ApplicationAdapter

///</summary>

[RemotingService]

publicclassMyApp:ApplicationAdapter

{

///<summary>

///应用程序启动

///</summary>

///<paramname="application"></param>

///<returns></returns>

publicoverrideboolAppStart(IScopeapplication)

{

Trace.WriteLine("应用程序启动");

returntrue;

}

///<summary>

///房间启动

///</summary>

///<paramname="room"></param>

///<returns></returns>

publicoverrideboolRoomStart(IScoperoom)

{

Trace.WriteLine("房间启动");

if(!base.RoomStart(room))

returnfalse;

returntrue;

}

///<summary>

///接收客户端的连接

///</summary>

///<paramname="connection"></param>

///<paramname="parameters"></param>

///<returns></returns>

publicoverrideboolAppConnect(IConnectionconnection,object[]parameters)

{

stringuserName=parameters[0]asstring;

stringpassword=parameters[1]asstring;

if(password==null||password==string.Empty)

thrownewClientRejectedException(null);

connection.Client.SetAttribute("userName",userName);

//获取共享对象(OnLineUsers)

ISharedObjectusers_so=GetSharedObject(connection.Scope,"OnLineUsers");

if(users_so==null)

{

//创建共享对象

CreateSharedObject(connection.Scope,"OnLineUsers",false);

users_so=GetSharedObject(connection.Scope,"OnLineUsers");

}

//更新共享对象

users_so.SetAttribute(userName,userName);

returntrue;

}

///<summary>

///加入房间

///</summary>

///<paramname="client"></param>

///<paramname="room"></param>

///<returns></returns>

publicoverrideboolRoomJoin(IClientclient,IScoperoom)

{

Trace.WriteLine("加入房间"+room.Name);

returntrue;

}

///<summary>

///离开房间

///</summary>

///<paramname="client"></param>

///<paramname="room"></param>

publicoverridevoidRoomLeave(IClientclient,IScoperoom)

{

Trace.WriteLine("离开房间"+room.Name);

base.RoomLeave(client,room);

}

///<summary>

///用户退出

///</summary>

///<paramname="connection"></param>

publicoverridevoidAppDisconnect(IConnectionconnection)

{

stringuserName=connection.Client.GetAttribute("userName")asstring;

ISharedObjectusers_so=GetSharedObject(connection.Scope,"OnLineUsers");

if(users_so!=null)

{

//从共享对象中移除当前退出系统用户

users_so.RemoveAttribute(userName);

}

base.AppDisconnect(connection);

}

}

}

开发好了ApplicationAdapter,还需要对此ApplicationAdapter进行通信配置,在FluorineFx的应用程序目录中添加app.config并进行如下配置:

<?xmlversion="1.0"encoding="utf-8"?>

<configuration>

<application-handlertype="Fx.Adapter.MyApp"/>

</configuration>

另外还需要配置一个客户端方法的通信通道,通过FluorineFx网站下的WEB-INF/flex/service-config.xml配置:

<?xml version="1.0" encoding="utf-8" ?>

<services-config>

<channels>

<channel-definitionid="my-rtmp"class="mx.messaging.channels.RTMPChannel">

<endpointuri="rtmp://{server.name}:1617"class="flex.messaging.endpoints.RTMPEndpoint"/>

</channel-definition>

</channels>

</services-config>

如上便完成了服务器端的开发,在flash/felx客户端通过NetConnection去连接应用,并根据当前的连接去连接服务器端的远程共享对象,最后通过异步事件来实现数据同步更新。如下程序运行截图:

Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)2

此时开多个浏览器窗口测试,不同窗口使用不同的用户名登录,可以很清楚的看到,我们已经实现了在线用户的数据同步功能,可以及时的反映用户上线离线,可以及时的同步在线用户列表的数据。

另外远程共享对象还有一个功能非常强大的特性方法,就是连接到共享对象的客户端之间可以直接广播消息(客户端调用客户端的方法)。就以上面在线用户的案例为例,用户成功登陆服务器我需要广播一条消息,用户退出了我也需要广播一条消息,要实现这个功能就需要通过远程共享的客户端呼叫 (send()方法)来实现,如下代码块:

privatefunctiononCallClient(message:String):void

{

so.send("onSayMessage",message);

}

远程共享对象的send()方法调用了onSayMessage这个客户端方法来实现对连接到共享对象上的所有客户端广播消息,那么我们的在定义一个onSayMessage方法,如下:

/**

*接受客户端呼叫---此方法必须是public修饰

*/

publicfunctiononSayMessage(message:Object):void

{

traceWriteln(message.toString());

}

private function traceWriteln(param:String):void

{

txtTraceArea.htmlText += param + "n";

txtTraceArea.validateNow();

txtTraceArea.verticalScrollPosition = txtTraceArea.maxVerticalScrollPosition;

}

Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)3

如果想实现用户退出广播,可以通过服务器端RPC的方法调用客户端的方法来实现,关于RPC请查看《Flex与.NET互操作(十一):基于FluorineFx.Net的及时通信应用(Remote Procedure Call)(二) 》有详细介绍。下面是Flex客户端的完整代码:

<?xmlversion="1.0"encoding="utf-8"?>

<mx:Applicationxmlns:mx="http://www.adobe.com/2006/mxml"layout="absolute"

width="530"height="378"backgroundGradientAlphas="[1.0,1.0]"

backgroundGradientColors="[#000000,#686868]"fontSize="12">

<mx:Script>

<![CDATA[

importmx.controls.Alert;

importdotnet.fluorinefx.VO.UserInfo;

privatevarnc:NetConnection;

privatevarso:SharedObject;

privatevarinfo:UserInfo;

privatefunctionconnectionServer(event:MouseEvent):void

{

info=newUserInfo();

info.UserName=this.txtUserName.text;

info.Password=this.txtPassword.text;

nc=newNetConnection();

nc.connect("rtmp://localhost:1617/SOAPP",info.UserName,info.Password);

nc.addEventListener(NetStatusEvent.NET_STATUS,onStatusHandler);

nc.client=this;

this.txtUserName.text="";

this.txtPassword.text="";

this.txtUserName.setFocus();

}

privatefunctiononStatusHandler(event:NetStatusEvent):void

{

this.connStatus.text="连接状态:"+event.info.code;

if(event.info.code=="NetConnection.Connect.Success")

{

//连接远程共享对象

so=SharedObject.getRemote("OnLineUsers",nc.uri,false);

if(so)

{

so.addEventListener(SyncEvent.SYNC,onSyncHandler);

so.connect(nc);

so.client=this;

}

onCallClient("用户【<fontcolor="#4100b9">"+info.UserName+"</font>】登陆了系统!");

");

}

}

privatefunctiononSyncHandler(event:SyncEvent):void

{

vartemp:Array=newArray();

for(varu:Stringinso.data)

{

//traceWriteln("异步事件->共享对象:"+u+":"+so.data[u]);

temp.push(so.data[u]);

}

this.userList.dataProvider=temp;

}

privatefunctiontraceWriteln(param:String):void

{

txtTraceArea.htmlText+=param+"n";

txtTraceArea.validateNow();

txtTraceArea.verticalScrollPosition=txtTraceArea.maxVerticalScrollPosition;

}

privatefunctiononCallClient(message:String):void

{

so.send("onSayMessage",message);

}

/**

*接受客户端呼叫

*/

publicfunctiononSayMessage(message:Object):void

{

traceWriteln(message.toString());

}

]]>

</mx:Script>

<mx:Labelx="24"y="134"id="connStatus"width="288"color="#FFFFFF"/>

<mx:Listx="342"y="10"height="347"width="160"id="userList">

</mx:List>

<mx:Formx="24"y="10"width="236">

<mx:FormItemlabel="用户名:"color="#FFFFFF">

<mx:TextInputid="txtUserName"width="130"color="#000000"/>

</mx:FormItem>

<mx:FormItemlabel="密码:"color="#FFFFFF">

<mx:TextInputid="txtPassword"width="130"

color="#000000"displayAsPassword="true"/>

</mx:FormItem>

<mx:FormItemlabel="">

<mx:Buttonlabel="登陆服务器"click="connectionServer(event)"

enabled="{this.txtUserName.text.length>0?true:false}"color="#FFFFFF"/>

</mx:FormItem>

</mx:Form>

<mx:TextAreax="24"y="174"width="288"height="153"alpha="1.0"

backgroundColor="#F2D2D2"backgroundAlpha="0.26"color="#FFFFFF"

id="txtTraceArea"borderColor="#FFFFFF"/>

</mx:Application>}

}

privatefunctiononSyncHandler(event:SyncEvent):void

{

vartemp:Array=newArray();

for(varu:Stringinso.data)

{

//traceWriteln("异步事件->共享对象:"+u+":"+so.data[u]);

temp.push(so.data[u]);

}

this.userList.dataProvider=temp;

}

privatefunctiontraceWriteln(param:String):void

{

txtTraceArea.htmlText+=param+"n";

txtTraceArea.validateNow();

txtTraceArea.verticalScrollPosition=txtTraceArea.maxVerticalScrollPosition;

}

privatefunctiononCallClient(message:String):void

{

so.send("onSayMessage",message);

}

/**

*接受客户端呼叫

*/

publicfunctiononSayMessage(message:Object):void

{

traceWriteln(message.toString());

}

]]>

</mx:Script>

<mx:Labelx="24"y="134"id="connStatus"width="288"color="#FFFFFF"/>

<mx:Listx="342"y="10"height="347"width="160"id="userList">

</mx:List>

<mx:Formx="24"y="10"width="236">

<mx:FormItemlabel="用户名:"color="#FFFFFF">

<mx:TextInputid="txtUserName"width="130"color="#000000"/>

</mx:FormItem>

<mx:FormItemlabel="密码:"color="#FFFFFF">

<mx:TextInputid="txtPassword"width="130"

color="#000000"displayAsPassword="true"/>

</mx:FormItem>

<mx:FormItemlabel="">

<mx:Buttonlabel="登陆服务器"click="connectionServer(event)"

enabled="{this.txtUserName.text.length>0?true:false}"color="#FFFFFF"/>

</mx:FormItem>

</mx:Form>

<mx:TextAreax="24"y="174"width="288"height="153"alpha="1.0"

backgroundColor="#F2D2D2"backgroundAlpha="0.26"color="#FFFFFF"

id="txtTraceArea"borderColor="#FFFFFF"/>

</mx:Application>

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Flash教程学习
热门Flash教程学习
网页设计子分类