`
hjoo
  • 浏览: 73496 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

FCS/FMS教程连载[转自世纪流年]

    博客分类:
  • FMS
阅读更多
1、开始
一、FlashCom开发所需安装的软件和硬件:
1. FlashMX authoring
2. FlashMX Communication Server
3. ActionScript editor (笔者推荐 editplus )
4. Flash Player
5. Camera and Micophone

二、设置开发环境
1. 确保FlashCom server已经启动
2. 更改运行FlashCom Server的URL地址
    new_nc.connect('rtmp:/video/room_01');//本地服务器
    或者使用
    new_nc.connect('rtmp://www.liu21st.com/video/room_01');//远程服务器
  如果使用simpleconnect组件,直接在组件的属性中设置即可
3. 指定发布格式
   一般为html和swf
4. 书写client-side 的as脚本,一般写在第一帧
5. 书写server-side的asc脚本,一般为main.asc或组件对应的app_name.asc
6. 加载组件,如果使用默认的组件,可以通过下面的语句简单加载
   load('components.asc');//该文件在scriptlib目录下面
7. 初始化 client-side 代码. 给第一行添加下面代码
     #include 'Netdebug.as'
     以便进行NetConnection 调试(ps.新版的FlashCom Server已经不包含netdebug.as文件,需要安装Flash Remote )
8. 监视应用程序
  通过FlashCom自带的应用程序管理器和管理工具来监控和管理 [ 中文版见这里 ]

三、大致开发步骤
1. 设定应用程序目录并在服务器端注册
   在服务器端的application目录下建立相应的子目录就可以了(也就是项目main.asc文件所放置的目录了)记住服务器端的任何改动都需要重启FlashCom Server才能生效
2.  在客户端建立链接

    my_nc = new NetConnection();
    my_nc.connect('rtmp://www.liu21st.com/app_name');//app_name即为新建的子目录名


3. 保存客户端的fla文件到任何地方(如果涉及后台交互的话建议保存在webserver目录下)
4. 如果包含client端需要相应的server端的asc文件,请拷贝到server端的相应目录(建议保持和客户端相同的文件名,而只是后缀不同)
5. 然后发布你的swf文件并运行

默认的服务器端asc文件存储位置在C:\Program files\Macromedia\Flash
Communication Server MX\applications in Windows or /opt/macromedia/flashcom/applications
on UNIX.当你需要创建一个communciation应用程序时,就需要在applications下面建立子目录,存放下面的数据文件:
  asc 服务器端通信文件
  flv  数据流播放文件
  fso 远程共享对象数据文件
客户端的swf和html(或者php等服务器文件)可以放在你指定的任何目录,在产品发布的时候需要移走fla源文件。
每一个应用程序的实例也位于不同的目录,如:
my_nc.connect('rtmp://www.liu21st.com/chatApp/room_01')
my_nc.connect('rtmp://www.liu21st.com/chatApp/room_02')


如果没有指定实例,客户端实际上连接到一个默认的名为_defInst_的实例,可以对不同的实例建立不同的共享对象
// One instance of application 'support'
first_nc = new NetConnection();
first_nc.connect('myserver.mydomain.com/support/session1');
first_so = SharedObject.getRemote('CustomerInfo', first_nc.URI, false);
first_so.connect(first_nc.URI);
 
// Another instance of application 'support'
second_nc = new NetConnection();
second_nc.connect('myserver.mydomain.com/support/session2');
second_so = SharedObject.getRemote('CustomerInfo', second_nc.URI, false);
second_so.connect(second_nc.URI);


四、在FlashCom中使用的文件类型
1. ASC 和 JS 文件 服务端使用的文件类型
   Flash Communication Server 在 服务端的scriptlib 目录下提供了一个脚本库,包含了一些组件和Flash Remoting services.的server端脚本
2. FLV 和 IDX 文件 视频播放文件和索引文件
3. SOL, SOR 和 FSO文件 共享对象数据文件(依次为Local、Remote和两者)




2、连接示例
首先确保服务器已经启动,在windows下面可以直接启动服务就可以了。在Linux下面需要运行 server start命令启动。
在客户端写代码打开连接
my_nc = new NetConnection();//创建连接对象
my_nc.connect(targetURI);//连接服务器
参数格式为:其中实例名可以省略
rtmp://localhost:port/appName/instanceName //本地服务器
也可以省略前面的直接写成
rtmp:/appName/instanceName
rtmp://host:port/appName/instanceName//远程服务器
注意协议类型一定要使用rtmp,否则会连接失败
下面是一个简单的实现方法:

1 : //获取和设置摄像头
2 : client_cam = Camera.get();
3 : Live_video.attachVideo(client_cam);


//建立远程连接

1 : function doConnect() {
2 : client_nc = new netConnection();
3 : client_nc.onStatus = function(info) {
4 : trace('Level: ' + info.level + ' Code: ' + info.code);
5 : }
6 : client_nc.connect('rtmp://localhost/doc_connect/room_01');
7 : }


//发布视频流

1 : function publishMe() {
2 : out_ns = new netStream(_root.client_nc);
3 : out_ns.attachVideo(client_cam);
4 : out_ns.publish('myTestStream');//采用默认的live播放形式
5 : }


//播放视频流

1 : function playMe() {
2 : in_ns = new netStream(_root.client_nc);
3 : Published_video.attachVideo(in_ns);
4 : in_ns.play('myTestStream');
5 : }


定义好这些函数后,就可以用下面的代码简单实现

1 : // Connect to the server
2 : doConnect();
3 : // Publish the live stream
4 : publishMe();
5 : // Play back the stream from the server
6 : playMe();




3、数据流
Flash Communciation Server 包含了server端(由一些asc文件组成)和client端(swf文件)
server端和client端的数据传输通过Real-Time Message Protocol (RTMP)进行实时交流,web server通过http服务把内容提供给client端,实现模式如下图:

多用户可以连接到同一个应用程序Application

Flash Communciation Server实际上为不同的用户之间提供了相互交流的通道。

基于客户/服务器模式的application,服务器端主要负责数据的传输,由客户端发送请求,服务器端执行数据查询和计算并返回结果值给客户端,通常需要保持长时间的连接。

Flash Communciation Server提供了两种方法控制用户的更多交互:数据流和共享对象.
数据流是指在服务器端和客户端同步传递的音频、视频和其它数据的信息流,数据流可以通过简单的发布和订阅方式实现。一个发布的数据流可以实时的被看到(如视频聊天室),

也可以被录制下来以后播放。

录制的数据流被存为Flash Video (FLV) 格式,其中可以包含文本、音频和视频等信息。当然你也可以把存在的通过第三方的软件录制的视频和音频文件转换为flv格式的文件。




4、共享对象
在FlashCom 开发过程种可以使用两种共享对象:本地和远程共享对象。
本地共享对象可以看作是Flash cookie,可以在用户的本地机器存放用户数据,其本身为Flash player提供,可以无须FlashCom Server的支持。
远程共享对象是由FlashCom Server来管理的,提供了信息和数据的同步,以及数据的存储。
Flash客户端连接、提交给远程共享对象,并且与服务器端保持同步。信息数据还可以发布到所有连接到远程共享对象的客户端,并通过应用程序的session或临时文件持续。更多的信息请参考共享对象类。


连接外部数据源
根据FlashCom的数据流和共享对象提供的交流模型,FlashCom Server还可以和外部数据源交互,例如web 服务器、关系数据库,甚至其它的FlashCom Server应用程序。例如,你可以写一个服务器端的脚本文件来连接一个web服务器或ColdFusion应用程序来接收一串用户名和电话号码的列表,然后把查询结果写入共享对象。详细的方法后面的章节会描述。


创建和开发应用程序的流程
你可以使用FlashMX创作工具来创建应用程序的客户端组件,生成的swf文件提供了应用程序的用户界面,其中也包含了与FlashCom Server连接和控制的as脚本。
服务器端则需要相关的应用程序目录,其中包含了运行客户端所需要的asc脚本,提供多个客户端之间逻辑控制和数据交换。

在开发应用程序的过程种,客户端程序需要发布到合适的位置以保证应用程序的正常运行,这通常要结合Web Server,如html、php、asp等,因为FlashCom Server采用rtmp协议,所以web server并非必须,你可以直接在swf文件中执行,但不推荐这样做。
服务器端程序(包含asc、flv等文件)需要放置到正确的应用程序目录下面。

如果你是一个FlashCom Server管理员,你可以使用管理控制台来配置FlashCom server、设置系统安全、监视使用情况,停止和重启server,还可以添加用户。这需要用来第一章提到的 应用程序管理器和管理工具




5、应用示例
下面内容主要讲述如果用如何通过客户端连接服务器,怎样访问共享对象,以及调用远程方法等。
当用户使用客户端的swf文件连接服务器时,服务器会加载应用程序,如果没有运行就创建实例。服务器端接受连接之后,产生一个新的客户端对象回应该客户端应用程序,执行指定的服务器端脚本。客户端需要做的是初始化数据流和共享对象等
连接流程
当客户端开始连接服务器后,服务器端会调用onAppStart方法(确保应用程序实例已经处于运行状态)
接下来,服务器端会回调客户端定义的onConnect方法,该方法的逻辑决定了是否接受该连接请求。当客户端断开连接的时候,会调用服务器端的onDisconnect方法;当应用程序结束后,会调用onAppStop方法


远程方法调用
在连接成功之后,客户端可以调用服务器端组件定义的方法,服务器端也可以调用客户端组件中的方法。
每一个连接到服务器端的应用程序都作为一个服务器端的客户对象实例,每一个客户端的实例对象都可以通过NetConnect对象调用远程服务器的方法,然后服务器端可以回应并返回值给客户端。下面的图表示了在客户端调用服务器端方法并获取返回值的方法:


从服务器端回调客户端的方法
从服务器回调客户端的方法比较类似于上面所说的。在客户端,可以给NetConnect对象的实例自定义方法,在服务器端可以利用client.call的方式调用客户端的方法。图示即为从服务器调用客户端并返回值的方法。


共享对象的使用
共享对象简化了在多用户之间共享数据的开发工作,一个Flash 客户端要获取远程共享对象可以通过 SharedObject.getRemote来指定连接,
然后通过SharedObject.connect连接远程共享对象,一旦连接成功,服务器端会发送同步信息给各个连接的客户端,客户端使用SharedObject.onSync来保持同步,下面的图简单描述了其使用过程。




6、对象概述
Macromedia Flash Communication Server MX 1.5提供了两部分API,即客户端API和服务器端API。本章主要讲述客户端API和服务器端API是怎样使用的。也会涉及到共享对象的讨论,怎样存储关于应用程序和用户的相关信息。概述FlashMX Com Server的核心对象之后,我们也会重点描述一些类的细节内容,例如Camera, Microphone, NetStream, Stream, System和 Video 对象以及关于如何优化应用程序、保护客户端对象和使得NetConnection对象更安全。
客户端API提供了: Camera(摄影机), Microphone(麦克风), NetConnection(联机),NetStream(串流), SharedObject(共享对象)和 Video(视频). 服务器端API提供了下面这些对象: Application(应用程序), Client(客户端), NetConnection(联机), SharedObject(共享对象)和 Stream(串流).
客户端对象
下面的对象只能用于客户端的as脚本中
Camera 对象:允许你从摄影机捕捉视频并追加到任何一个MC中,当使用FlashMx Com server的时候,还可以在联机对象间传输、显示,甚至录制捕捉到的视频。应用这个特性,你可以开发例如视频会议、视频聊天等应用程序。
Microphone 对象 :该对象用于取得麦克风的声音来源,并且可以在联机对象之间传输、播放等,可以开发例如语音聊天之类的应用程序,如果不使用联机对象,也可以把声音通过音箱在本地输出。
NetConnection 对象:允许Flash客户端通过TCP socket与FlashCom Server建立连接,并且使用RTMP(Real-
Time Messaging Protocol,实时讯息通讯协议)交互数据。
NetStream 对象:在使用Netconnect对象所建立的联机对象上,进行数据、声音和视频信息的传输,就如同NetConnect的通道一样。
可以使用NetStream.publish方法来发步数据流,使用NetStream.play来播放接收到的数据流。
Localshared 对象:记录用户的资料,或者把讯息实时传递给所有联机用户。
Video 对象:用于显示通过NetStream.play方法或Camera.get方法捕捉到的视频流。并通过Video.attachVideo方法把该视频对象放置到flash的舞台。
服务器端对象
Application 对象:包含应用程序实体的信息与状态,直到程序结束为止。Application对象也可以让程序决定是否接收用户的联机或者关闭用户的联机,以及清除应用程序特定的流、清除在服务器端的共享对象,并让你在有效范围内访问整个应用程序的变量、定义相关事件所执行的函数等。
Client 对象:包含每个联机用户的信息,例如客户端的IP地址、Flash的版本信息、分配用户的频宽,或者呼叫客户端定义的方法等。
NetConnection 对象:可以在应用程序实体和服务器端,或者同一台服务器的另外一个应用程序之间创建一种双向的连接。你甚至可以使用服务器端的 NetConnection 对象来创建更强大的应用程序,例如你可以获取天气信息从另一个应用程序服务器或者和其他的Flashcom服务器及应用程序实体共享加载。使用联机对象,你可以使用标准的http协议或者rtmp协议在服务器之间交互和传递数据。
Remoteshared 对象:远程共享对象是在客户端建立的,但是可以在服务器端仍然可以使用,它可以实时地在客户端的多个应用程序之间共享和存储数据
SharedObject对象:作用和客户端建立的远程共享对象一样,让不同联机用户能够通过服务器端的共享对象实时分享信息。不过所提供的方法和客户端的有所区别。例如,读取服务器端的共享对象要用get方法,设定存储资料不用data属性,而使用setproperty和getProperty方法,另外还有暂时锁住和解锁的方法lock和unlock,防止资料会覆写。
Stream 对象:处理影音串流,传回录像文件的时间秒数、呼叫客户端串流对象中的自定义方法、以及播放与录像等方法。

客户端和服务器端的对象交流
某些对象的方法是可以在客户端或者服务器端建立和相互调用。例如当客户端的NetConnect对象联机到服务器端,服务器端的Netconnect对象同时也建立了,这个对象可以调用客户端NetConnect对象的副本的所有方法。下面的表格显示了对应的调用关系

 
客户端对象
 
my_nc (NetConnection object )
 
my_ns (NetStream object )
 
my_so (remote shared object )
 
回应的服务器端对象
 
my_client (Client object or application.clients object )
 
my_server_stream (Stream object )
 
my_server_so (server-side shared object )
 




下面表示了客户端的调用和服务器端的回应

 

 
客户端的调用
 
my_nc. connect
 
my_nc. close
 
my_nc.call('doThing', myCallbackFcn, 1, 'foo' )
 
my_so.send('doThing', 1, 'foo' )
 
服务器端的回应分别对应为
 
application. onConnect
 
application. onDisconnect

my_client.doThing(1, 'foo' )

my_server_so.doThing(1, 'foo' )





下面显示了服务器端的调用和客户端的回应

 

 
服务器端的调用
 
my_client.call ('doThing', myCallbackFcn,1, 'foo' )
 
my_server_stream.send ('doThing', 1,'foo' )
 
my_server_so.send('doThing', 1, 'foo' )
 
客户端的回应分别对应为
 
my_nc.doThing (1, 'foo' )
 
my_ns.doThing (1, 'foo' )
 
my_so.doThing(1, 'foo' )




7、理解共享对象
共享对象可以存储任何Flash支持的数据类型。就存放位置来说,共享对象可以分成存在客户端计算机的本地型,以及存放在服务器上的远程型。你可以用它来记录用户的相关信息(如用户名、性别和其它设置参数等),或者用在服务器端,存储其它联机用户实时分享的信息(如聊天室的内容和线上用户名单等)
共享对象意味着用户可以在不同的用户之间、不同的同一台服务器上的应用程序实体。FlashCom server 支持三种不同的共享对象:Local、remote和server-side。下面简单介绍下这三个共享对象。

本地共享对象(Local shared object)
用于存取本地的数据,存储在用户的计算机硬盘中,并可以在不同的时间被其它应用程序访问。本地共享对象的扩展名为.sol,默认的存储路径是c:\documents and Settings\登录名称\Application Data\Macromedia\Flash Player\服务器网域名称\影片路径\影片文件名.swf\。本地共享对象也可以是短暂的,也就是说只有但应用程序运行时可用。我们也可以不连接Flashcom server而使用本地共享对象。更多的本地共享对象的信息,可以参考手册中的SharedObject.getLocal方法。
建立和存取本地共享对象的方法如下:

var so= SharedObject.getLocal('myCookie') //建立本地共享对象

//存储资料

//注意:不管是读取还是写入资料到本地共享对象,都必须通过data属性。

so.data.userName='liu21st' ;

so.data.msg='世纪流年' ;

so.data.counter=10 ;

//在默认状态下,以上资料并不会马上写入用户的磁盘,必须等到动画被关闭,或者用户离开你的网站后,才会写入磁盘。如果要立即写入的话,必须使用flush方法。如下:

so.flush();



确认资料是否存储成功可以通过onstatus事件来获取
返回的code值为

SharedObject.Flush.Success(写入成功)
SharedObject.Flush.Failed(写入失败)
代码示例:

so.onStatus = function (info){

var status=info.code ;

if (status=='SharedObject.Flush.Success' ){

   trace('写入成功' ); }

else trace('写入失败');



远程共享对象(remote shared object)
通过Flash影片的ActionScript程序,在服务器端建立能让不同联机用户共同存取的资料,称为远程共享对象。和本地共享对象一样,远程共享对象可以被本地计算机存取,不同的是在资料存储在服务器端,所以任何用户都可以连接到远程共享对象访问到相同的信息。默认的存储路径是应用程序实体路径下的sharedobjects文件夹,扩展名是.fso。
远程共享对象也是最常用的共享对象类型。每当联机用户(或服务器端程序)更新远程共享对象的内容,其它联机到相同应用程序实体的用户将自动收到更新内容的事件(onSync),保持彼此资料的同步。聊天室应用程序就是运用这个机制建立的。
例如,你可以打开一个远程共享对象,如电话号码表(在服务器端持久有效)。当用户端对该共享对象作任何更改的时候,修改后的数据对其他连接到该远程共享对象的用户是自同步的。如果因为某种原因,更新了本地的数据信息但是没有连接到服务器,那么所作的更改会在下一次连接到服务器的时候同步远程共享对象。
更多的信息可以参考手册中的SharedObject.getRemote方法。

建立远程共享对象的方法:

var client_nc = new NetConnection();

client_nc.connect('rtmp://localhost/videochat/room1' );

so = SharedObject.getRemote('records',client_nc.url); //数据资料不写入磁盘

so.connect(client_nc);



远程共享对象的数据读取和写入方法和本地共享对象类似,也是通过data属性和flush方法。
使用下面语句可以把数据资料写入服务器端应用程序文件夹共享对象目录

so = SharedObject.getRemote('records',client_nc.url,true);

//该语句远程共享的文件名将是records.fso



当远程共享对象的内容改变或者初次联机时,它都会向客户端发出onsync (同步)事件,好让所有联机用户都能实时取得最新的共享对象资料。
示例代码:

so.onSync = function(list) {

for (var k in  list) {

trace('name = ' + list[k].name + ', event = ' + list[k].code );

}

// do whatever else you want to do here

}



代理共享对象(proxied shared object)
代理共享对象是可以在用户端和服务器端共享的一种远程共享对象,区别在于它是由服务器端的ActionScript程序建立的,例如,在服务器端有两个聊天室的实体chat01和chat02,在chat02中可以连接到在chat01中定义的共享对象,更多的信息可以参考手册的SharedObject.get方法。
和客户端的sharedobject不同,设置共享变量的值要通过 SharedObject.setProperty,取得共享变量的值通过 SharedObject.getProperty 。
实例代码:

application.appStart = function() {

     nc = new NetConnection ();

     nc.connect('rtmp://' + master_server + '/' + master_instance );

     proxySO = SharedObject.get('myProxy',true,nc );  

     // Now, whenever the client asks for a persistent

    // shared object called myProxy they will receive myProxy

    // shared object from the master_server/master_instance

};




myInfo = SharedObject.get('foo');

var addr = myInfo.getProperty('address' );

myInfo.setProperty('city', 'San Francisco' );

var names = sharedInfo.getPropertyNames ();

for (x in names ){

  var propVal = sharedInfo.getProperty(names[x ]);

  trace('Value of property ' + names[x] + ' = ' + propVal );

}



在使用远程共享对象之前,请确认SharedObject.connect 返回 true,在客户端调用SharedObject.flush 方法只是在本地拷贝了一份,要确保服务器端的拷贝,必须在服务器端使用SharedObject.flush 方法,如:

 
// Sample server-side code for flushing a persistent shared object
 
// to the server
 
// Get the shared object when the application is loaded.
 
application.onAppStart  = function()
 
{
 
application.mySO = SharedObject.get('SharedObjName', true );
 
}
 
// When a user disconnects, flush the shared object.
 
application.onDisconnect = function(client )

{

application.mySO.flush ();

}



如果在同一时间有多个客户端或者服务器端在同步远程共享对象的话,就会出现问题,要解决这个冲突可以通过下面的方法。
1. 使用不同的位置存储不同用户的信息
  这是最简单的一种方法,例如,在聊天室给每个用户不同的位置存放数据,同步只修改自己的数据部分。
2. 分配资料所有者
  复杂一点的方法就是定义一个用户为有限的时间内该数据资料的所有者,所有者可以锁定服务器端的共享对象,直到返回可用信息后方可同步另外的数据。下面是示例代码:
通过一个记录游戏最高分的应用程序来说明解决同步冲突的问题,当前系统保存的最高分是95,同时有两个用户打破了这个记录,成绩分别为105和110,如果不锁定最高分的话,两个成绩都会同时执行updateHighScore方法,有可能其中一个成绩会无法记录下来。使用锁定共享对象的方法解决了这样一个问题。

 
application.onAppStart = function()
 
{
 
application.scoreSO = SharedObject.get('high_score_so', true );
 
application.scoreSO.onSync = function(listVal )
 
{
 
trace('got an onSync on scoreSO' );
 
}
 
}
 
application.onConnect = function(newClient,name,passwd )

{

newClient.updateHighScore = function(final_score )

{

application.scoreSO.lock ();

if (application.scoreSO.getProperty('high_score_so') < final_score )

{

application.scoreSO.setProperty('high_score_so', final_score );

}

application.scoreSO.unlock ();

}

}



3. 通知客户端
当服务器端收到客户端的同步请求的时候,SharedObject.onSync事件会通知用户端更改被拒绝,然后提供一个用户界面来给用户解决这种冲突。这种技术通常用于客户端不是经常更新的情况。
4. 接受某些,拒绝其它的
应用程序根据“先到先服务”的原则来解决同步的冲突问题。通常需要于客户自己重新请求来解决冲突。
5. 通过send方法来提高控制级别
SharedObject.send 命令给所有连接到该远程共享对象的客户端广播消息,也包括发送者本人。




8、Application对象
Application对象可以让你接受或拒绝用户端的连接请求,注册客户端相应事件的类和方法等。一般在服务器端的main.asc文件中定义相关事件。
服务器端的程序由下列事件程序组成:

1 : application.onAppStart = function(){
2 : //应用程序初次启动时,要执行的程序
3 : //并且只会被执行一次
4 : }



1 : application.onConnect = function(){
2 : //每当有用户链接到此应用程序时,要执行的程序
3 : //可以在这里读取用户端的数据
4 : //建立可以让客户端执行的方法
5 : //或者呼叫客户端的自定义方法等
6 : }

如果使用communication server组件的话,还可以使用Application.onConnectAccept 和 application.onConnectReject事件
可以查看下面的实例程序:

01 : // A user has connected
02 : application.onConnect = function( newClient, userName )
03 : {
04 : if (userName == 'admin')
05 : {
06 : newClient.adminFunc= function(param)
07 : {
08 : // some code that’s only useful to the admin
09 : newClient.myAdminProperty = param;
10 : }
11 : } else
12 : {
13 : // code for most cases
14 : }
15 : // Allow the logon
16 : application.acceptConnection( newClient );
17 : }
18 : // this part could be in a separate file
19 : // Every client (including admin) is going to have this function
20 : // (because of the way 'prototype' works).
21 : Client.prototype.commonFunction = function (myColor)
22 : {
23 : // some code
24 : // use this to refer to the client instead of newClient
25 : this.color = myColor;
26 : }

或者

01 : application.onConnect = function(clientObj,name,passwd)
02 : {
03 : // First accept the connection
04 : application.acceptConnection(clientObj);
05 : // After client is registered with the application instance
06 : // you can use 'call' method
07 : clientObj.call('onWelcome', 'You are now connected!!!');
08 : return;
09 : // Once you call acceptConnection or
10 : // rejectConnection within onConnect, return value is ignored.
11 : }

注意:如果要call客户端的方法,请确认已经调用application.acceptConnection以保证客户端正常连接。


1 : application.onDisConnect = function(){
2 : //当用户离线时,要执行的程序
3 : //可以在这里清楚用户的数据
4 : //和其它相关的程序
5 : }

可以参考下面的程序:

01 : // On the server side you would have the following
02 : application.onConnect = function(newClient, name)
03 : {
04 : newClient.name = name;
05 : return true;
06 : }
07 : application.onDisconnect = function(client)
08 : {
09 : for (var i = 0; i < application.clients.length; i++)
10 : {
11 : application.clients[ i ].call('userDisconnects', client,name);
12 : }
13 : }
14 : // On the client side you would have the following
15 : nc = new NetConnection();
16 : nc.userDisconnects= function (name) {
17 : trace(name + 'quits');
18 : }
19 : nc.connect ('rtmp:/app_name', userName);



1 : application.onAppStop = function(){
2 : //应用程序结束时,要执行的程序
3 : //也就是说所有的联机用户都离线后
4 : //这里的程序会被执行
5 : }


我们看到的main.asc文件可能并没有包含上面的任何一个事件,那是因为有可能通过load方法加载了其它的组件定义,但是我们仍然可以在main.asc文件中定义我们需要的事件和方法。




9、Camera对象
这一节主要讲述camera对象的使用,包括camera的使用优化、设置合适的带宽和如果使得一个camera用于多个应用程序。
Camera对象允许你从摄影机捕捉视频并追加到任何一个MC中,当使用FlashMx Com server的时候,还可以在联机对象间传输、显示,甚至录制捕捉到的视频。应用这个特性,你可以开发例如视频会议、视频聊天等应用程序。当然你也可以不通过服务器来使用Camera对象,例如可以捕捉你的视频并附加到某个MC。
Camera常用的属性:

 
bandWidth 每秒种传送的最大字节数
 
currentFps 当前传送的fps值
 
fps setMode方法设定的fps值
 
name 当前使用的摄像机名称
 
names 可用视频捕捉设备的数组
 
index 可以视频设备的索引值
 
keyFrameInterval 关键帧间隔
 
loopback 是否压缩影像
 
motionLevel 灵敏度0~100 数值越高动作越迟钝

width 影像的宽度

height 影像的高度

quality 传送的影像品质0~100

muted 客户端是否允许Flash取用本地端的摄像机



需要创建Camera对象,使用下面代码:

1 : MyCamera = Camera.get();
2 : //如果有多个视频设备,请使用index(索引值)指定设备
3 : MyCamera = Camera.get(index);
4 :

如果在不同的网域访问,就会弹出窗口让用户确认使用或是拒绝使用:



当用户对弹出窗口响应后就会触发onStatus事件,请参考muted参数
当然也可以记住用户的选择,点击鼠标右键出现设置窗口



在该窗口选择允许,并选中记住,下次就不会弹出确认窗口了。
更高级的示例是弹出设备选择窗口让用户选择:

1 : camArray = Camera.names;
2 : if (camArray.length == 1){
3 : Camera.get();
4 : }
5 : else
6 : System.showSettings(3);//弹出视频设置窗口
7 : Camera.get();





Flashcomguru 的 arckid 提供了一个很好的检测Camera的方法,把它略作修改如下

01 : function checkforCam() {
02 : camArray = Camera.names;
03 : if (camArray.length >= 1){
04 : temp_cam = Camera.get();
05 : if(temp_cam == -1)
06 : trace('视频设备正忙');
07 : else
08 : trace('视频设备可用');
09 : delete temp_cam;
10 : } else if (camArray.length == 0) {
11 : trace('没有视频设备');
12 : }
13 : }
14 : //-----------------------------------------------------------------
15 : //或者下面的函数更精简:
16 : function checkForCam(){
17 : return Camera.names.length;
18 : }
19 : function isCamBusy(){
20 : if(arguments.length) return Camera.get(arguments[0]) == -1;
21 : return Camera.get() == -1;
22 : }
23 :


要设置Camera对象的模式,可以用setMode()方法,如下:

1 : MyCamera.setMode(width, height, fps [, favorSize])
2 : //width,height 是Camera对象宽高,默认值是160×120
3 : //fps 捕捉视频的速率 默认值是15
4 : //favorSize 是一个可选的布尔值,默认为true,表示采用最大匹配当前的窗口大小的速率,如果设为false,则会优先考虑影像的流畅度。

不同带宽的建议设置
默认的Camera设置对所有的带宽提供了一个相同的足够好的传输品质,如果需要手动设置以适应不同的带宽要求,设置Camera参数的方法如下:

MyCamera.setQuality(bandwidth, frameQuality)

//bandwidth 频宽指每秒传送的最大字节数 默认为16384 如果设为0则维持frameQuality设定的影像品质,尽量使用最大频宽

//freamQuality 影像的压缩品质1~100,设为0表示在bandwidth设定范围内自动调整影像品质




下面对不同的带宽给出了建议设置:

 
[ Modem  ]
 
较低画质,较高动作流畅度 my_cam.setQuality(4000,0 )
 
较高画质,较低动作流畅度 my_cam.setQuality(0,65 )
 
[ DSL  ]
 
较低画质,较高动作流畅度 my_cam.setQuality(12000,0 )
 
较高画质,较低动作流畅度 my_cam.setQuality(0,90 )
 
[ LAN  ]
 
较低画质,较高动作流畅度 my_cam.setQuality(400000,0 )
 
较高画质,较低动作流畅度 my_cam.setQuality(0,100)


打开和设置完Camera之后后要附加到一个视频实体才可以显示

MyVideo.attachVideo(MyCamera);



正常关闭camera
如果你的应用程序使用camera对象和NetStream对象记录数据,camera仍然保持打开状态,为了确保关闭Camera对象,请在结束的时候使用

NetStream.attachVideo(false)



在多个应用程序中使用同一个Camera
多个应用程序(swfs)可以在同时使用一个Camera。一般而言,多个浏览器窗口使用相同的进程,所以在浏览器环境中多个应用程序可以正常使用同一个Camera。但是,如果一个是在浏览器中运行,一个是独立应用程序,就不能共享使用同一个Camera,因为Camera不能被多个进程共享。

事件响应
在Camera有两个重要的事件响应
1. onStatus事件 muted属性变化会触发该事件
原参考手册中的一个示例可以说明onstatus的用法

01 : myCam = Camera .get ();
02 : myVideoObject.attachVideo(myCam);
03 : myCam.onStatus = function ( infoMsg ) {
04 : if ( infoMsg.code == 'Camera.Muted' )
05 : {
06 : trace ( 'User denies access to the camera' );
07 : }
08 : else
09 : trace ( 'User allows access to the camera' );
10 : }
11 : // Change the Allow or Deny value to invoke the function
12 : System .showSettings(0);


2. onActivity事件 视频是否活动的事件响应
请参考原手册的范例:

1 : // Assumes a Video object named 'myVideoObject' is on the Stage
2 : c = Camera.get();
3 : myVideoObject.attachVideo(c);
4 : c.setMotionLevel(10, 500);
5 : c.onActivity = function (mode)
6 : {
7 : trace(mode);
8 : };




10、Microphone对象
这一节讲述如何使用Microphone对象,包括怎么减少麦克风的回音。

获取麦克风

1 : Microphone.get([index]);
2 : //一般如果只有一个麦克风的话,可以用Microphone.get()

来自flashcomguru forums的检测麦克风函数:

01 : function checkforMic() {
02 : micArray = Microphone.names;;
03 : if (micArray.length >= 1){
04 : temp_mic = Microphone.get();
05 : if(temp_mic == -1)
06 : trace( '--- mic is detected but its busy' );
07 : else
08 : trace( '--- mic detected' );
09 : delete temp_mic;
10 : } else if (micArray.length == 0) {
11 : trace( '--- no Mic detected' );
12 : }
13 : }
14 :

或者使用下面的更简单的函数:

01 : function checkForMic(){
02 : return Microphone.names.length;
03 : }
04 :
05 : // trace ('User have a Mic? -> '+checkForMic());
06 :
07 : function isMicBusy(){
08 : if(arguments.length) return Microphone.get(arguments[0]) == -1;
09 : return Microphone.get() == -1;
10 : }
11 : // trace ('Is user's Mic busy? -> '+isMicBusy());


避免回音
如果你使用外置的话筒,因为会有较大的增益,就不可避免的遇到回音的问题。
为了尽量降低话筒的回音,FlashCom Server提供了回音抑制功能。要使用这一功能,可以通过下面的方法:

myMicrophone.useEchoSuppression(true);


这样就可以保持较好的语音效果,而不会从话筒传递过多的的回音。但尽管如此,仍然会有部分的回音无法消除,下面是一些好的建议:
1. 适当调低你的话筒音量
2. 让话筒远离你的音箱
3. 及时查找你的设备故障
4. 如果可以尽量使用戴在头上的耳机或听筒

保持Microphone始终打开
为了节约带宽,FlashCom server默认会关闭Microphone对象当它不再使用的时候。但是,有时候你可能需要保持Microphone保持始终打开(例如为了保证没有任何延迟),你可以使用下面的方法:

my_mic.setSilenceLevel(0)



音量调节
Flashcomguru上提供了如何调节音量的方法:

1 : //Attach your netstream audio to a movielcip:
2 : movieclip_mc.attachAudio(yournetStream);
3 : // create a sound object
4 : my_snd = new Sound(movieclip_mc);
5 : // to adjust the volume
6 : my_snd.setVolume(50);




11、NetConnect对象
对象简介
如果要把本地端的视频或者声音传递给其它的客户端,Flash影片就必须要联机到FlashCom 服务器。联机的方法就是通过NetConnect对象的connect()方法,连接到指定路径的FlashCom应用程序。
FlashCom使用RTMP协议来共享和传输你的数据、声音和视频。

对象属性:
isConnected 是否连接
uri 连接的URL地址,可以使用下面的方式
? rtmp://www.myCompany.com/myMainDirectory/groupChatApp/HelpDesk
? rtmpt:/sharedWhiteboardApp/June2002
? rtmp::1234/chatApp/room_name

例如你要联机到vchat的聊天程序,并且进入room1房间,可以按照下面的方式写:

1 : //建立联机对象
2 : client_nc = new NetConnect ();
3 : //联机到应用程序实体
4 : client_nc.connect( 'rtmp://mywebsite.com/vchat/room1' );

可以不写房间名,则进入默认的房间
详细的连接语法可以参考我之前的笔记:连接示例 。

NetConnect对象并不支持http协议,所以类似下面的连接方式是错误的:

myConn.connect('http://www.mydomain.com/myfile.php?id= 0001') ;


并且FlashCom服务器端不支持任何直接远程调用的方法如 getURL 或 LoadVars,也就是说,服务器端不能够和后台程序进行数据交换,必须使用call方法调用客户端方法或者使用FlashRemote(或者使用开源的PHPObject)。

远程呼叫
如果要呼叫远程服务器端的方法或指令,可以使用Call方法,该方法的格式如下:

1 : call (方法名称,接收传回值的对象(没有就用null),[参数1,参数2,...])
2 : //参数列表为需要传递到服务器端方法的参数,如果参数多余会被服务器端忽略

和很多对象一样,NetConnect对象有个onStatus事件,用于接受返回信息
下面是比较常见的写法:

1 : client_nc.onStatus = function (info){
2 : //处理状态信息的程序代码
3 : };
状态信息的类型记录在信息对象的level属性中,其可能值为
status 状态
warning 警告
error 错误
信息的内容则记录在对象的code属性中。在NetConnect对象中,可以参考下面的范例程序来输出返回信息:

01 : client_nc.onStatus = function (info){
02 : trace ( '信息类型:' + info.level + newline + '信息内容:' + info.code );
03 : switch (info.code){
04 : case 'NetConnection.Connect.Success':
05 : trace ( '联机成功!' );
06 : break;
07 : case 'NetConnection.Connect.Failed':
08 : trace ( '联机失败!' );
09 : break;
10 : case 'NetConnection.Connect.Closed':
11 : trace ( '联机中断!' );
12 : break;
13 : }
14 : };


保存日志
需要的话可以把连接日志记录下来:

1 : client_nc.onStatus = function(info)
2 : {
3 : _root.log += 'Recording stream status.\n' ;
4 : _root.log += 'Event: ' + info.code + '\n' ;
5 : _root.log += 'Type:' + info.level + '\n' ;
6 : _root.log += 'Message:' + info.description + '\n' ;
7 : }


关闭连接
要关闭连接请使用 close()方法,如下面的代码停止数据流对象后关闭连接

1 : function disconnect() {
2 : // Stops publishing the stream.
3 : srcStream.close();
4 : // Deletes the source stream connection.
5 : connection.close();
6 : }




12、NetStream对象
NetStream对象是在所有联机对象之间传递影音串流。如果你仅仅是为了传递文字聊天内容,使用共享对象就可以解决,不必要使用这个对象。
该对象的基本属性有
time 到目前为止,串流资料播放的秒数
bufferTime 缓冲区的最大秒数
currentFps 当前播放影像的速率(每秒帧数)
bufferLength 当前缓冲区的资料秒数
liveDelay 实时播放视频流的间隔
但是当你想知道当前播放的影像的总长度的时候,必须调用服务器端的方法才可以,因为客户端的FlashPlayer是无法获知数据流的总长的。你需要在客户端写如下方法:

01 : function getInfo()
02 : {
03 : nc.call( 'sendInfo', new MyResultSetName(), myStream);
04 : }
05 : function MyResultSetName()
06 : {
07 : this.onResult = function ( retVal )
08 : {
09 : _root.streamlength = retVal;
10 : };
11 : this.onStatus = function(info)
12 : {
13 : trace ( 'Level:' + info.level + 'Code:' + info.code);
14 : // process error object
15 : };
16 : }


然后在服务器端的main.asc文件中的相关事件中写入:

01 : application.onAppStart = function ()
02 : {
03 : trace('::: Application has started :::');
04 : }
05 : application.onConnect = function (client)
06 : {
07 : application.acceptConnection (client);
08 : // Add methods
09 : client.prototype.sendInfo = function (name) {
10 : var slen = Stream.length (name);
11 : trace ( 'slen:' + slen);
12 : return slen;
13 : };
14 : }


相关方法参考:
setBufferTime ( 秒数)
可以设置缓冲区的大小以提高低品质的网络情况
注意:bufferLength大小总是不大于bufferTime

attachVideo ( 影像来源,[ 拍摄模式 ] )
将摄像机对象的影像追加给串流对象,如果影像来源为null,将停止捕捉影像
拍摄模式省略表示捕捉连续的影像;若为0则只拍摄单元格画面;大于0,将以此数值为秒数间隔,连续拍摄单元格影像。

attactAudio ( 声音来源 )
将麦克风的音源设定给串流对象

publish ( 串流资料名,[ 播出方式 ])
如果串流资料名没有指定则停止播出
播出方式有live(默认值)实时播出但不存储;record 播出同时以串流资料名.flv文件存储,路径为应用程序路径下面的streams文件夹;append 播出的同时追加到指定名称的flv文件中,如果不存在,则自动创建。

pause()
暂停、开始播放

close ()
停止发布或播放当前所有数据流,把 NetStream.time 属性设置为 0, 使得其它客户端可以使用该数据流,该方法当你使用 NetStream.play() 或NetStream.publish() 的时候被隐含调用

play( 串流名称,起始时间,长度,是否清除前一个串流 )
起始时间默认值为-2 表示flash会先尝试播放实时影音,否则就播放指定识别名称的文件
若为-1 将只播放实时影音 若为0 将只播放指定名称的录像内容
长度参数指定影音播放的秒数 默认为-1 表示一直播放到结束 为其它值为播放到指定秒数的内容

receiveVideo(fps)
指定播放串流的速率fps设定为0时,flash将停止播放影像

seek(秒数)
快倒倒录像文件倒指定秒数的画面,如果设为0,则跳转到开头
可以使用相对时间来跳转,如
client_ns.seek(client_ns.time-3)

如果要在传输音频或视频流的同时,包含文本数据等,也就是说进行数据交换,则可以使用send方法。
可以在客户端包含下面的actionscript:

1 : var my_nc:NetConnection = new NetConnection();
2 : my_nc.connect('rtmp://myServer.myDomain.com/appName/appInstance');
3 : var my_ns:NetStream = new NetStream(my_nc);
4 : my_ns.publish('slav', 'live');
5 : my_ns.send('Fun', 'this is a test');

在接收端可以使用下面代码:

1 : var my_nc:NetConnection = new NetConnection();
2 : my_nc.connect('rtmp://myServer.myDomain.com/appName');
3 : my_ns = new NetStream(my_nc);
4 : my_ns.play('slav', -1, -1);
5 :
6 : my_ns.Fun = function(str) { //Fun is the handler name
7 : trace (str);
8 : }


关闭视频流的几种方法:

1 : myStream_ns.publish(false);// 停止整个串流
2 : myStream_ns.close();//关闭串流,当然也就停止了串流播放
3 : mystream_ns.attachVideo(null);//仅仅停止视频播放,仍然保持音频播放




13、Video对象
视频对象用来显示实时的或者录制的视频流。视频对象显示的可以是通过Camera.get方法捕捉到的实时视频,也可以是通过NetStream.play方法播放的实时的或者录制的视频文件和MP3音频文件。
为了能够显示视频流,首先要放置视频对象到舞台,然后使用video.attachVideo方法附加视频流到视频对象即可。

1 : my_cam = Camera.get();
2 : my_video.attachVideo(myCam); // myVid 是放置到舞台的一个视频对象

视频对象的使用类似于MC,和其它可放置到舞台的对象一样,你可以设置不同的属性。视频对象的常用属性有:
width 视频对象的宽度
height 视频对象的高度
deblocking 是否使用deblocking过滤,默认为0自动适应,1为从不使用,2总是使用
smoothing 是否使用平滑过渡,默认为false不使用,true则使用平滑过渡(需要高品质播放模式)
下面的例子说明了如何发布、录制和回放视频

01 : // 实时播放的同时录制视频文件
02 : //录制的视频文件名为 'allAboutMe.flv'
03 : var my_nc:NetConnection = new NetConnection();
04 : my_nc.connect('rtmp://localhost/allAboutMe/mySpeech');
05 : var publish_ns:NetStream = new NetStream(my_nc);
06 : publish_ns.publish('allAboutMe', 'record');
07 : publish_ns.attachVideo(Camera.get());
08 :
09 : // 播放录制的视频文件
10 : // 注意:播放录制文件不需要再发布视频流
11 : var my_nc:NetConnection = new NetConnection();
12 : my_nc.connect('rtmp://localhost/allAboutMe/mySpeech');
13 : var subscribe_ns:NetStream = new NetStream(my_nc);
14 : subscribe_ns.play('allAboutMe');
15 : my_video.attachVideo(subscribe_ns); // my_video是一个视频对象实体


如果要清除当前的视频对象,可以使用clear方法

1 : my_video.clear();

需要注意的是,清除视频对象并不意味着中断连接,要中断数据流在视频对象中的播放,可以这样处理:

1 : my_video.attachVideo(null);




14、System对象
系统对象是Flash的一个顶层对象,主要用来设置系统参数和安全定义。
常用属性有:

System.useCodepage 是否使用网页字符格式,默认为false 格式是utf-8
System.exactSettings 访问本地设置是否使用超级域匹配规则 Flash7新增属性


常用的方法有:

System.showSettings( [panel] ) 显示系统设置对话框
0 隐私设置
1 本地存储设置
2 麦克风设置
3 摄像机设置
为空则显示用户最近设置

System.setClipboard( string ) 设置剪贴板文字 Flash7以后支持
用指定的字符串替换当前的剪贴板内容


system对象也具有onStatus事件响应,我们看下下面的代码:

01 : // 定义响应方法
02 : System.onStatus = function( genericError )
03 : {
04 : // Your script would do something more meaningful here
05 : trace('An error has occurred. Please try again.');
06 : }
07 :
08 : // 创建一个 NetStream 对象的方法
09 : // 如果NetStream 对象返回错误
10 : // System.onStatus 将被触发
11 :
12 : videoStream_ns.onStatus = function(infoObject) {
13 : if (infoObject.code == 'NetStream.Play.StreamNotFound') {
14 : trace('Could not find video file.');
15 : }
16 : }




15、客户端信息对象
在FlashCom中的Camera, Microphone, LocalConnection, NetConnection,NetStream和SharedObject对象都提供了onStatus事件响应,onstatus事件的返回信息记录在信息对象中。为了能够响应这些事件,你必须创建一个方法来处理信息对象,而最重要的一点是你必须要清楚不同的信息对象返回值和返回类型。
信息对象具有下面的属性。
code 记录信息的返回内容
level 信息等级状态,有status 状态 warning 警告 error 错误
下面对FlashCom中的对象的onstatus返回值作个总结。


Camera信息对象
Camera.Muted (Status)
用户拒绝使用camera
Camera.Unmuted (Status)
用户允许使用camera

LocalConnection信息对象
none (status)
none (error)

Microphone信息对象
Microphone.Muted (Status)
用户拒绝使用microphone.
Microphone.Unmuted (Status)
用户允许使用microphone.

NetConnect信息对象
NetConnection.Call.Failed (Error)
NetConnection.call方法调用服务器端的方法或命令失败
NetConnection.Connect.AppShutdown (Error)
服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭.
NetConnection.Connect.Closed (Status)
连接中断
NetConnection.Connect.Failed (Error)
连接失败
NetConnection.Connect.InvalidApp (Error)
指定的应用程序名称没有找到
NetConnection.Connect.Rejected (Error)
连接被拒绝
NetConnection.Connect.Success (Status)
连接成功

NetStream 信息对象
NetStream.Buffer.Empty (Status)
数据缓冲区为空
NetStream.Buffer.Full (Status)
缓冲区已慢
NetStream.Failed (Error)
传输中有错误发生
NetStream.Pause.Notify (Status)
播放暂停
NetStream.Play.Failed (Error)
播放出错
NetStream.Play.PublishNotify (Status)
发布开始,信息已经发送到所有订阅者
NetStream.Play.Reset (Status)
播放列表重置
NetStream.Play.Start (Status)
播放开始
NetStream.Play.Stop (Status)
播放停止
NetStream.Play.StreamNotFound (Error)
播放的实时流或文件不存在
NetStream.Play.UnpublishNotify (Status)
发布停止,信息已经发送到所有订阅者
NetStream.Publish.BadName (Error)
发布的数据流已经被发布
NetStream.Publish.Idle (Status)
发布者闲置过长
NetStream.Publish.Start (Status)
发布开始
NetStream.Record.Failed (Error)
录制文件出错
NetStream.Record.NoAccess (Error)
没有足够的文件访问权限
NetStream.Record.Start (Status)
文件录制开始
NetStream.Record.Stop (Status)
录制暂停
NetStream.Seek.Failed (Error)
数据流定位出错
NetStream.Seek.Notify (Status)
数据搜索定位成功
NetStream.Unpause.Notify (Status)
恢复播放
NetStream.Unpublish.Success (Status)
停止发布

ShareObject信息对象
SharedObject.BadPersistence (Error)
SharedObject.getRemote方法传递的参数不匹配
SharedObject.Flush.Failed Error
写入失败
SharedObject.Flush.Success (Status)
写入成功
SharedObject.UriMismatch (Error)
SharedObject.connect的url参数和SharedObject.getRemote方法不一致

注意:对于NetStream、NetConnect和远程共享对象而言,在联机情况下onStatus有更多的返回值,这些返回值将会在服务器端信息对象中介绍,其它对象无须联机也可以响应到返回值。

针对以上不同的对象可以指定各自的onstatus方法,Macromedia 在Flash中提供了一个“超级”函数叫做System.onStatus ,如果某个对象的onstatus响应的level属性是error,并且没有指定响应操作的时候,Flash会触发System.onStatus事件。
下面的例子演示了如何创建通用的或者特殊的方法来处理信息对象:

01 : //创建通用方法
02 : System.onStatus = function (genericError)
03 : {
04 : // 在这里写上详细的处理代码
05 : trace( 'An error has occurred. Please try again.' );
06 : };
07 : // 创建NetConnection对象的onstatus响应方法
08 : // 如果连接返回的值在响应事件中没有定义,并且是error等级的话
09 : // System.onStatus 事件会被响应
10 : nConn.onStatus = function (infoObject)
11 : {
12 : if (infoObject.code == 'NetConnection.Connect.Success' )
13 : {
14 : trace( 'Successful connection.' );
15 : }
16 : if (infoObject.code == 'NetConnection.Connect.Failed' )
17 : {
18 : trace( 'Connection failed.' );
19 : }
20 : };
21 : // Attempt to open connection
22 : nConn = new NetConnection();
23 : nConn.connect( 'rtmp://myServer.myDomain.com/myRTMPapp' );




16、SharedObject对象
在FlashCom中的Camera, Microphone, LocalConnection, NetConnection,NetStream和SharedObject对象都提供了onStatus事件响应,onstatus事件的返回信息记录在信息对象中。为了能够响应这些事件,你必须创建一个方法来处理信息对象,而最重要的一点是你必须要清楚不同的信息对象返回值和返回类型。
信息对象具有下面的属性。
code 记录信息的返回内容
level 信息等级状态,有status 状态 warning 警告 error 错误
下面对FlashCom中的对象的onstatus返回值作个总结。


Camera信息对象
Camera.Muted (Status)
用户拒绝使用camera
Camera.Unmuted (Status)
用户允许使用camera

LocalConnection信息对象
none (status)
none (error)

Microphone信息对象
Microphone.Muted (Status)
用户拒绝使用microphone.
Microphone.Unmuted (Status)
用户允许使用microphone.

NetConnect信息对象
NetConnection.Call.Failed (Error)
NetConnection.call方法调用服务器端的方法或命令失败
NetConnection.Connect.AppShutdown (Error)
服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭.
NetConnection.Connect.Closed (Status)
连接中断
NetConnection.Connect.Failed (Error)
连接失败
NetConnection.Connect.InvalidApp (Error)
指定的应用程序名称没有找到
NetConnection.Connect.Rejected (Error)
连接被拒绝
NetConnection.Connect.Success (Status)
连接成功

NetStream 信息对象
NetStream.Buffer.Empty (Status)
数据缓冲区为空
NetStream.Buffer.Full (Status)
缓冲区已慢
NetStream.Failed (Error)
传输中有错误发生
NetStream.Pause.Notify (Status)
播放暂停
NetStream.Play.Failed (Error)
播放出错
NetStream.Play.PublishNotify (Status)
发布开始,信息已经发送到所有订阅者
NetStream.Play.Reset (Status)
播放列表重置
NetStream.Play.Start (Status)
播放开始
NetStream.Play.Stop (Status)
播放停止
NetStream.Play.StreamNotFound (Error)
播放的实时流或文件不存在
NetStream.Play.UnpublishNotify (Status)
发布停止,信息已经发送到所有订阅者
NetStream.Publish.BadName (Error)
发布的数据流已经被发布
NetStream.Publish.Idle (Status)
发布者闲置过长
NetStream.Publish.Start (Status)
发布开始
NetStream.Record.Failed (Error)
录制文件出错
NetStream.Record.NoAccess (Error)
没有足够的文件访问权限
NetStream.Record.Start (Status)
文件录制开始
NetStream.Record.Stop (Status)
录制暂停
NetStream.Seek.Failed (Error)
数据流定位出错
NetStream.Seek.Notify (Status)
数据搜索定位成功
NetStream.Unpause.Notify (Status)
恢复播放
NetStream.Unpublish.Success (Status)
停止发布

ShareObject信息对象
SharedObject.BadPersistence (Error)
SharedObject.getRemote方法传递的参数不匹配
SharedObject.Flush.Failed Error
写入失败
SharedObject.Flush.Success (Status)
写入成功
SharedObject.UriMismatch (Error)
SharedObject.connect的url参数和SharedObject.getRemote方法不一致

注意:对于NetStream、NetConnect和远程共享对象而言,在联机情况下onStatus有更多的返回值,这些返回值将会在服务器端信息对象中介绍,其它对象无须联机也可以响应到返回值。

针对以上不同的对象可以指定各自的onstatus方法,Macromedia 在Flash中提供了一个“超级”函数叫做System.onStatus ,如果某个对象的onstatus响应的level属性是error,并且没有指定响应操作的时候,Flash会触发System.onStatus事件。
下面的例子演示了如何创建通用的或者特殊的方法来处理信息对象:

我似乎反复的在讲共享对象了,实在是我觉得共享对象在FlashCom开发中太重要了,甚至可以说是FCS的灵魂。
之前的关于共享对象的文章可以参考我的笔记:
共享对象概述
理解共享对象
还有一篇转载的:共享对象

shared Object对象相当强大,他提供了在多个客户端实时数据共享,并且可以存储在客户端或远程服务器。可以把本地共享对象比作cookies,把远程共享对象看作实时的数据传输设备。
通常共享对象的使用方法如下:
1. 保持本地永久存储
这是最简单的共享对象应用。并且不需要FlashCom Server的支持。例如,你可以使用SharedObject.getLocal方法来创建一个本地共享对象。因为本地共享对象是永久存储的,用户端Flash结束的时候会通过data属性保存在客户端本地机器中。当下一次运行swf文件的时候,就可以直接存取到。如果你在影片播放结束的时候把共享对象的属性置空了,下一次就存取不到任何的值了。
2. 在服务器端共享和存储数据
存储在服务器端的共享对象数据可以被其它联机的客户端取到。例如,你打开了一个远程共享对象,该共享对象中存储了一个电话清单。当客户端对该共享对象数据有任何更改的时候,改变的数据对所有联机对象都是自同步的。如果对象暂时无法连接到服务器端,那么所作的更改将会在下一次更新到服务器端。
3. 实时交流数据
共享对象可以实时的在多个客户端之间共享数据。你可以打开一个存储实时数据的远程共享对象,例如,一个连接到聊天室的用户列表,当有用户进入或离开聊天室的时候,该共享对象会实时更新,所有连接到该服务器的客户端将立刻看到用户列表的更改。
下面的例子演示了一个简单的共享对象的使用,记住在创建一个远程共享对象之前,必须先使用NetConnect对象联机到服务器。

01 : // Create a local shared object
02 : so = SharedObject.getLocal('foo');
03 : // Create a remote shared object that is not persistent on the server
04 : nc = new NetConnection();
05 : nc.connect('rtmp://server.domain.com/chat/room3';
06 : so = SharedObject.getRemote('users', nc.uri);
07 : so.connect(nc);
08 : // Create a remote shared object that is persistent on the server
09 : // but not on the client
10 : nc = new NetConnection();
11 : nc.connect('rtmp://server.domain.com/chat/room3';
12 : so = SharedObject.getRemote('users', nc.uri, true);
13 : so.connect(nc);
14 : // Create a remote shared object that is persistent on the server
15 : // and on the client
16 : nc = new NetConnection();
17 : nc.connect('rtmp://server.domain.com/chat/room3';
18 : so = SharedObject.getRemote('users', nc.uri, '/chat');
19 : so.connect(nc);

规划远程共享对象
要规划远程共享对象,我们应该先设计一个数据管理模型。我们需要做的是数据字段设计和管理、冲突解决、客户端和服务器端的存储分析,我们针对这些方面一一说明。
如果要使用本地存储的远程共享对象,请确保swf的舞台尺寸大于215×138像素,否则将无法正常显示设置面板。
数据设计和管理
共享对象关联的数据存储在共享对象的data属性中,要设置共享对象的值可以使用下面的方式:

1 : //建立本地共享对象,没有则自动创建
2 : var so = SharedObject.getLocal('local_so');
3 : //为共享对象中的变量赋值
4 : so.data.userID = 'Liu21st';
5 : so.data.currentStatus = 'onLine';
6 : so.data.lastLogon = '2004-06-30';

如果要创建客户端的私有存储,可以不通过data属性,如:

1 : so.userID = 'Liu21st';
2 : so.currentStatus = 'onLine';
3 : so.lastLogon = '2004-06-30';

对共享对象的data属性赋NULL或undefined可以初始化字段
so.data.userID = NULL ;
但是并没有删除该字段,如果要删除请用:
delete so.data.userID;
我们也可以使用类似于
so.data.year.month.dayOfMonth = someValue;的方式来赋值
//注意该赋值并非一个字段 year.month.dayOfMonth
//而分别是给三个字段 year,month,dayOfMonth 初始化相同的值

但是不推荐使用该方式,因为这样在同步的时候会始终占用较多的带宽
使用分开赋值的方式可以避免每次同步全部数据
so.data.year = someValue;
so.data.month = someValue;
so.data.dayOfMonth = someValue;
你可以根据应用程序的需求来设计共享对象的变量。如果共享对象中的值都需要频繁更新,尽可能减少共享对象的字段可以提高性能。
站长经常使用的方式是:

1 : so.data.user = { id:1,sex:b,name:liu21st }
2 : // 在存取的时候可以使用
3 : // so.data.user.name的方式


冲突解决
如果多个客户端在同时更新数据的话,冲突就产生了。必须制定冲突解决策略,下面是常用的方法。
1. 尽量使用不同的字段
最简单的方法是给每个客户端或服务器端分配不同的字段。例如,为聊天室中的每个用户设定一个字段,并且每个用户只能更改自己的字段。
2. 分配拥有者
更高级的策略是分配一个客户端作为共享对象属性的短期拥有者,你可以锁定对象的属性被写入,在有其它客户端对该属性的更新时候向拥有者发送请求。如果请求成功,表示只有一个客户端更改该共享对象数据。
3. 通知客户端
当服务器拒绝客户端的更改请求的时候,SharedObject.onSync事件会通知客户端该更改暂时被拒绝,然后,应用程序可以提供一个用户界面让用户再次发送。这个策略比较适用于不定期更新的数据,还有一个好处是当冲突发生时,客户端可以选择接收或拒绝更改。
4. 选择性更改
某些应用程序按照“先到先服务”的原则来定制策略,这种方式适用于用户可以重新递交同步请求当其他人更新完成之后。
本地存储空间的考虑
你可以选择让远程共享对象存储在客户端、服务器或者两者,本地共享对象总是存储在本地客户端,直到没有可用空间为止。
默认的存储空间大小是100K,如果企图存储更多的数据,Flash会弹出一个本地存储对话框,让用户允许或拒绝本地存储。
如果用户选择允许,数据将被保存,并且SharedObject.onStatus事件触发,返回的code属性值为 SharedObject.Flush.Success,如果选择拒绝,数据存储失败,code属性值为SharedObject.Flush.Failed,用户也可以选择打开本地存储面板,进行存储空间大小设置,并且记住当前的选择。
在actionscript中无法设置本地存储空间的大小,必须通过弹出对话框的形式让用户操作,如果需要,请使用:
System.showSettings(1)

共享对象的方法总结
SharedObject.close
//关闭远程共享对象和服务器的连接
SharedObject.connect
//连接到服务器端的一个远程共享对象
SharedObject.flush
//立即写入本地共享对象数据
//如果不使用系统会在下列情况自动完成写入
// swf文件关闭,sharedObject.close调用,共享对象被回收
// 如果对远程共享对象使用该方法,只会在客户端写入,而不会在服务器端写入,如果要完成服务器端的写入请使用下面的代码:

01 : // This is a SERVER-SIDE script, not ActionScript
02 : // Get the shared object when the application is loaded.
03 : application.onAppStart = function()
04 : {
05 : application.mySO = SharedObject.get( 'SharedObjName' , true);
06 : }
07 : // When a user disconnects, flush the shared object.
08 : application.onDisconnect = function(client)
09 : {
10 : application.mySO.flush();
11 : }
12 : // You can also set a timer to periodically flush the shared object
13 : // onto the hard disk on the server
14 : application.onAppStart = function()
15 : {
16 : application.mySO = SharedObject.get( 'SharedObjName' , true);
17 : setInterval(function() { application.mySO.flush(); }, 60000);
18 : }

SharedObject.getRemote
//创建一个远程共享对象
SharedObject.getSize
//取得当前(本地或远程)共
分享到:
评论
1 楼 为你而来 2008-04-21  
好啊!!正需要这个!!多谢了

相关推荐

Global site tag (gtag.js) - Google Analytics