fms帮助文档中文服务器编程

Adobe flash media server  开发者向导
1   起步
  Adobe  flash  meida  server 提供了一个流媒体的集合和为建立富媒体应用的群集交互模
式。Flash media server 提供了即时开始,实况视频流和基于用户带宽的可变的流的码率。
  Flash media server 有三个版本
  Flash Media Interactive Server  :拥有完整特性的服务
  Flash Media Development Server:一个用于开发的交互式服务的版本。支持所有的特性,
但是有连接数的限制。
  Flash Media Streaming Server:只支持实况和视频点播的服务。这个版本不支持服务器
端的脚本或视频编码。
  注释:在使用这个向导之前最好阅读 flash media server  技术一般观察
1. 1 前言
1.1.1   client‐server体系结构
  Flash media  server是一个网络中心,应用程序联用实时信息协议(real‐time messaging
protocol)连结到这个中心,这样服务器可以向连接到服务器上的很多用户发送数据并且从
这些用户接受数据。一个用户通过一台配备了摄像头和麦克风,并且安装了 flash  player 的
电脑可以捕捉实况视频或音频,然后通过服务器向全世界成千上万的用户发布自己的视频或
音频。全世界的用户可以参与在线游戏,并且同步所有用户的动作。
  用户通过网络连接连到服务器。一个连接类似于一个大的管道,这个管道里面传输着大
量的数据流。每个流在客户端和服务器之间传输。每个服务器可以并发的处理很多连接,最
大的连接数量取决于您的服务器的能力。
  一个在 flash media server上运行的应用程序后一个 client‐server体系结构。客户端的应
用程序是由 adobe flash  或 adobe flex 开发,运行在 flash player,AIR  或 flash lite 3  上的。他
可以捕捉和播放音频和视屏并且处理用户的交互。服务器端的应用程序运行在服务器上。它
可以处理客户端的连接,向服务器的文件系统写入文件,并且处理其他的任务。
  客户端必须向服务器发起连接。一旦连接成功,客户端可以和服务器或其他客户端通信。
确切的说,客户端连接到一个服务器上运行的应用程序的实例。一个应用程序的实例的例子
是一个有着很多不同房间的在线游戏,用户可以组成很多不同的组群来进行游戏。在这个例
子里面,每个房间就是一个确定的应用程序的实例。
  许多应用程序的实例可以同时运行。每一个应用程序的实例有自己唯一确定的名字,并
且向客户端提供独一无二的资源。多个用户可以连接到同一个应用程序的实例或不同的应用
程序的实例
 
多个客户端连接到运行与 flash media server的多个应用程序(如图的 scrabble 和 sudoku)和
多个应用程序的不同实例实例(如 scrabble 的 room2 和 sudoku 的 room1和 room2)
1.1.2媒体应用程序的组成部分
  客户端的应用程序用 actionscript 编写并且被编译为 swf 文件。服务器端的应用程序是
由服务器端的 actionscript 编写(一种类似于 actionscript 1.0 的语言,但是不在客户端运行,
而是在服务器端运行)。一个媒体应用程序通常有已经编码好的或者实况的音频和视频,它
们通过流的方式由服务器传输到客户端,由客户端传输到服务器或由服务器传输到服务器。  
  一个典型的 flash meida server应用程序有以下几个部分:
  客户端的用户界面:客户端的显示着用户界面,如控制视频开始,停止或暂停的按钮。
用户界面可以运行在 flash player,AIR  或 flash lite 3  上,由 adobe flash  或 adobe flex 开发。  
  客户端的 actionscrip:客户端有可以处理用户交互和连接到服务器的 actionscript 的代
码。Flash media server3 支持 actionscript3.0。客户端由 actionscript2.0 或actionscript1.0 为早
期版本的 Flash media serve而开发的因应用程序也是被 Flash media server3 兼容的。
  视频或音频:许多媒体应用程序将已经编码好的音频或视频以流的方式由服务器端传输
到客户端,或由一个客户端传输到服务器端然后到其他的客户端。事先编码好的文件可能是
Flash Video  (FLV), MP3,  或  MP4 格式的。又服务器端编码的视频总是 FLV 格式的,以.Flv 为
后缀.
  摄像头或麦克风:一个客户端可以用 Adobe Flash Media Encoder或者你自己的习惯的支
持实况流的 flash 软件向服务器实况传输音频或视频。客户通过自己的摄像头和麦克风端捕
获音频或视频。
  服务器端的 actionscript:许多应用程序包括封装在一个以.asc 为后缀的服务器端的
actionscript 代码里面,通常叫他 actionscript 通信文件。这个文件被命名为 man.asc 或
myApplication.asc。服务器端的脚本处理服务器端的任务,如流通传输音频和视频,定义当
用户连接或断开连接时做什么。具体的请查看服务器端 actionscrip 语言参考。
1.1.3流格式
  Flash media  server支持很多种流媒体格式,包括 Flash  Video  (FLV), MPEG‐3  (MP3),  and
MPEG‐4 (MP4)。
1.2 搭建开发环境
1.2.1安装服务
  你可以使用免费开发版的服务来开发和测试应用程序。最简单的开发环境是一台安装了
flash 或 flex 的电脑,这台电脑通同时被用作服务器。
  安装服务
  如果你需要细节介绍的话请参考 Adobe Flash Media Server  安装向导。
  开启服务
  当你安装服务时,你可以设置开机自动开启服务。如果服务没有开启,你可以手动开启。  
  1.点击开始,选择所有程序>adobe> Flash Media Server 3 > Start Flash Media Server 3。
  2.点击开始,选择所有程序>adobe>  Flash  Media  Server  3  >  Start  Flash  Media
Administration Server 3。
  注释:如果你像打开管理控制台的话你需要开启 Administration Server服务。
  确认服务运行
  打开控制面板>管理工具>服务。在服务窗口,确认 Flash Media Administration Server  和
Flash Media Server都被开启。
1.2.2安装flash
  使用 actionscript3.0 开发 flash 用户界面,你需要 flash   cs3 和 flash player 9。
  1.下载并且安装 Adobe Flash CS3 Professional。
  2.下载并且安装 Flash Player 9。
  3.打开 flash   cs3,选择文件>发布设置。
  4.在格式栏里面确保 flash 和 html 被选中。
  5.在 flash 栏里面,对于版本选项,选择 flash  player  9。对于 actionscript 选项,选择
actionscript3.0。
 
1.2.3安装flex
创建用户界面,你需要 Adobe Flex Builder  或  Adobe Flex SDK 和flash player 9。
  1.下载并且安装 Adobe Flex 2 SDK  或  Adobe Flex Builder 2。
  2.下载并且安装 Flash Player 9。
  3.在 Flex Builder 里面确保 project> Build Automatically被选中。
1.3 hello world 应用程序
1.3.1前言
注释:下面的部分应用于 Flash Media Interactive Server  和 Flash Media Development Server者
两个版本的服务。
  这个例子使用 flash CS3 来展示如何将一个 flash 文件连接到一个服务器端的脚本,别且
如何从服务器获取数据。在这个例子里面,flash 用户界面有一个按钮(connect)和一个
lebel(最初是空的)。当一个用户点击 connect 按钮,客户端连接到服务器;然后客户端运行
服务器端的函数来返回一个字符串的值。当服务器端回应了,客户端的回应函数在 label 上
显示字符传。客户端通过改变按钮的 label 来断开连接。当 diaconnect 的按钮被点击,客户
端断开连接,并且清空 label。
范例文件在 HelloWorld 文件夹下。
1.3.2创建用户界面
  1.开启 Flash CS3,然后选择新建>flash 文件(ActionScript 3.0)。
  2.在文档类的框框里面写上 HelloWorld。你可能看见一个关于威定义的 actionscript 类警
告信息。点及 ok,因为你将添加类文件在下一节。
3.选择窗口>组件,然后选择 User Interface>Button。在属性栏里面为按钮取名 connectBtn。
4.添加一个 Label 组件,移动它到按钮上面,取名为 textLbl。
保存文件为 HelloWorld.fla。
 
 
 
1.3.3编写客户端脚本
这个脚本定义了两个按钮动作,一个是连接到服务器,另一个是从服务器断开。当连到
服务器,这个脚本或调用服务器端的一个函数传入参数(”world”),这将引发一个相应来显
示返回的字符串(”hello world”)。
1.选择文件>新建>actionscript 文件。检查目的路径有 HelloWorld.fla。
2.声明包和导入需要的类;
package {     
     import flash.display.MovieClip;
     import flash.net.Responder;
     import flash.net.NetConnection;
     import flash.events.MouseEvent;
     public class HelloWorld extends MovieClip {
     }
}
3.为连接和相应服务器事件申明变量(查看  ActionScript 3.0  语言和组件参考)
private var nc:NetConnection;
private var myResponder:Responder = new Responder(onReply);
4.定义类的构造函数。设置 label 和 button 的显示的值,为 button 添加事件侦听器
public function HelloWorld() {
     textLbl.text = "";
     connectBtn.label = "Connect";
     connectBtn.addEventListener(MouseEvent.CLICK, connectHandler);
}
5.基于按钮当前的 label 定义侦听函数
public function connectHandler(event:MouseEvent):void {
         if (connectBtn.label == "Connect") {
             trace("Connecting...");
             nc = new NetConnection();
             //  连接到服务器
             nc.connect("rtmp://localhost/HelloWorld");
             //掉用服务器端的函数  serverHelloMsg,  在  HelloWorld.asc 里面.
             nc.call("serverHelloMsg", myResponder, "World");
             connectBtn.label = "Disconnect";                 
         } else {             
             trace("Disconnecting...");
             //  断开连接
             nc.close();
             connectBtn.label = "Connect";
             textLbl.text = "";
         }
}
6  定义相应函数(查看  ActionScript 3.0  语言和组件参考),用以设置 label 上显示的值。  
private function onReply(result:Object):void {
     trace("onReply received value: " + result);
     textLbl.text = String(result);
}
7.保存文件 HelloWorld.as。
我的学习:这里接触到了到了新的类 Responder 类和 NetConnetction,以前没用到过。
NetConnection 这个类在  Flash  Player  和  Flash  Media  Server  应用程序之间或者  Flash
Player  和运行  Flash Remoting  的应用程序服务器之间创建双向连接。   NetConnection  对
象如同客户端与服务器之间的管道。  可使用  NetStream  对象通过此管道发送流。在 call
方法中的一个参数要用到 Responder 的对象, call方法第一个参数是在服务器端的一个函
数名,第二给是 Responder 对象,用来处理通信的一些状态,后面的就是调用服务器端
函数的要传入的参数。Responder 的构造函数里面有两个 Function 类型的参数
result:Function  —  如果对服务器的调用成功并返回结果,则此函数被调用。
status:Function (default = null) —  如果服务器返回一个错误,则此函数被调用。者两个
函数在程序里面来实现,貌似result的参数就是服务器函数的返回值,由与帮助里面没找
到,猜测是这样的。
1.3.4编写服务器端脚本
  1.选择文件>新建>actionscript 通信文件。
  2.定义服务器端函数和连接的逻辑:
application.onConnect = function( client ) {
     client.serverHelloMsg = function( helloStr ) {
         return "Hello, " + helloStr + "!";
     }
     application.acceptConnection( client );
}
  3.在 RootInstall/application 的文件夹下创建一个叫 HelloWorld 的文件夹。
  4.把 HelloWorld.asc 文件保存在 RootInstall/application/HelloWorld 文件夹里面。
1.3.5编译和运行应用程序
  1.确认服务正在运行
  2.选择 HelloWorld.fla 文件中的菜单栏。
  3.选择控制>测试影片
  4.点击 Connect 按钮,Label 上就显示了”Hello  World!”,然后按钮上的文字就变成了
Disconnect。
  5.点击 Disconnect 按钮,Trace()语句执行,输出面板里面显示了相关内容。
1.4 创建一个应用程序
1.4.1编写客户端代码
  一个客户端用actionscript编码来连接到服务器,处理事件,和做其它工作。 通过flash CS3
你可以使用 actionscript 3.0,2.0 或1.0,但是 actionscript3.0 提供更多特性。要想使用 flex,你
必须使用 actionscript 3.0.
  Actionscript3.0 显著的不同于 actionscript 2.0。这个向导假设你是在正在编写 actionscript
3.0 的类,这些类是一些外部的.as文件,有符合你的开发环境的目录结构的包的名称。
  在 flash 里面创建一个 actionscript 3.0的类
  1.如果 actionscript 文件和 FLA 文件在同一个目录下,包名是不需要的:
package {
}
  2.如果你将文件保存在 FLA 的子目录下,包名必须匹配.as文件的路径,比如:
package com.examples {
}
  3.加入到粗语句和类声明:
package {
     import flash.display.MovieClip;
 
     public class MyClass extends MovieClip {
     }
}
类名需要和文件名相同而不管.as 文件的扩展。你的类可能导入或者扩展了其他的
actionscript3.0 的类,比如 MovieClip。
  在 Flex里面创建 actionscript3.0 的类
  1.开启 adobe flex builder。
  2.创建一个新的 Project。选择 File>New>Actionscript Project 然后跟随向导。如果你创建
了一个 actionscript 项目,一个已经被声明了包名和类名的 actionscript3.0 的文件就被打开:
package {
     import flash.display.Sprite;
 
     public class Test extends Sprite  
     {
         public function TestAs( )
         {
         }
     }
}
3.(可选)如果你创建一个 Flex Project  ,选择 File>New>ActionScript Class。

1.4.2编写服务器端代码
  通常来说,如果应用程序需要做一下任何的事情,就需要由服务器端的 actionscript 编
写的服务器端代码。
  客户端认证:通过用户名和密码,或者存储在应用程序或数据库里面的信用凭证来进行
客户端的认证。
  实现连接逻辑:当客户端连接或断开连接时做出反应来实现连接的逻辑。
  更新客户端:通过调用远端客户端的方法或更新 shared  objects来影响所有的连接到服
务器的客户端来跟新客户端。
  处理流:同过允许你播放,录音和管理传入和传出服务器的流来进行流的处理。
  连接到其他的服务器:通过调用网络服务或创建简介到一个服务器应用程序或数据库的
网络套接字来连接到其他的服务器。
  扩展服务:通过使用获取,授权或文件改编来扩展服务。
 
  将你的服务器端代码放到一个名为 main.asc 或 yourApplicationName.asc 的文件里面
yourApplicationName 就是你的已经在 flash media interactive server里注册的应用程序名字。
要在服务器上注册一个应用程序,在 RootInstall/applications 文件夹下创建一个以应用程序
的名字命名的文件夹就可以了。例如,要注册一个名为 skatingClips 的应用程序,就创建文
件夹 RootInstall/applications/skatingClips 即可。服务器端的代码就放在 skatingClips  文件夹下
的 main.asc  或  skatingClips.asc 文件里面。
  要配置 application 路径的位置,需要编辑 fms.ini  或  Vhost.xml 配置文件。具体的查看
Adobe Flash Media Server配置和管理向导。
  服务器端的代码放在 application 目录下或它的 script 的子目录下,例如你可以使用下面
的任意的路径:
RootInstall/applications/sudoku
 
RootInstall/applications/sudoku/scripts
 
1.4.2.1Client和application对象
  服务器端的脚本有权使用两个对象:Client 对象和 application 对象。当一个客户端简介
到一个在 flash media server上的应用程序时。服务器创建了一个服务器端的 Client 类的实例
来代表客户端。一个应用程序可以被成千上万的客户端连接。在你的服务器端的代码中,你
可以使用 Client 对象来和独立的客户端发送和接受数据。
  每一个应用程序也有一个单独的 application 对象,application 对象是一个服务器端的
Application 类的一个实例。application对象代表了应用程序的实例,你可以使用他来接受客
户端的连接请求,断开客户端的连接,关闭应用程序等诸如此类的事情。
1.4.2.2编写双字节的应用程序
  如果你使用双字节的文本(如亚洲的字集)来编写服务器端的 asctionscript 脚本,那么
请用 UTF‐8 的编码来编写。这个意味着你需要一个 JavaScript 的编辑器如 Flash  或
Dreamweaver 里面的脚本窗口,他们将文件编码为 UTF‐8 标准。然后你可以使用内置的
Javascript 方法如 Date.toLocaleString()方法来将字符串转换到系统的本地编码。
  有些简单的文件编辑器可能不会将文件编码为 UTF‐8 便准,然而有些编辑器,如微软的
Windows XP  和  Windows 2000 中的记事本提供了将文件另存为 UTF‐8 标准的选项。
 
在 Dreamweaver 中设置为 UTF‐8 编码
  1.检查文件的编码设置,选择修改>页面属性,然后文件编码,选择 Unicode(UTF‐8)。
  2.改变内置输入设置,选择编辑>首选参数(windows)或 Dreamweaver>首选参数(Mac),
然后点击常规,选择允许双字节内联输入。
 
使用双字节作为方法名
  使用对象数组的操作符而不要用点操作符来标记方法名,如:
//  这是正确的使用双字节字符来标记方法名的方法
obj["Any_hi_byte_name"] = function(){}  
 
//这是不正确的使用双字节字符来标记方法名的方法.
obj.Any_hi_byte_name = function() {}  
 
1.5 测试应用程序
1.5.1测试和调试服务器端脚本
  要测试一个服务器端的脚本,使用 trace()语句在显示器上显示每个过程点
  使用管理控制台来开始,停止,重载和查看应用程序采用一下方法:开始>所有程序>
Adobe Flash Media Server 3 > Flash Media Administration Console.
  注释:当你编辑和保存一个.asc 文件时,只有应用程序重新开始后才会产生影响。如果
应用程序已经运行,使用管理控制台关闭它,谈后再次连接这个应用程序。
 
  对于每个应用程序的实例而言,你可以检查他的实况记录,客户端和 shared  objects,
如果需要的话,还可以检查正在使用的流和运行状态。
  下面是一个检查正在运行的应用程序的运行表现的例子
 
 
查看服务器端脚本的输出
main.asc 文件里面 trace()语句输出的内用被发送到一个日志文件里面,典型的如下
RootInstall/logs/_defaultVHost_/yourApplicationName/yourInstanceName/application.xx.log
yourApplicationName 是默认的, XX 是实例的数字, 00 值最近用到的日志, 01 是上一个实例,
以此类推。
 
  你可以通过任何的文件编辑器来查看日志
  当一个应用程序正在运行,你可以在管理控制台里面看它的实况日志:
  1.在 window 桌面,点击开始>所有程序>  Adobe  Flash  Media  Server  3  >  Flash  Media
Administration Console。
  2 当管理控制台打开了,点击 View Applications,  然后 Live Logs.  
 
1.5.1.1使用管理控制台调试
  调式会话的可用性和数量是在 Application.xml 文件里面的 AllowDebugDefault  和
MaxPendingDebugConnections  这两个参数决定的。默认的,调式是不被允许的。要知道更
多的细节,查看 Adobe Flash Media Server  配置和管理向导。
  你可以添加下面的代码来重写调式设置
Application.allowDebug = true;
注释:如果使用了这个代码,在最后配置应用程序是将它改成 false
 
开始调式会话:
1.开启 Flash Media Server  和  Flash Media Administration Server。
2.开启管理控制台。
3.使用安装是设置的用户名和密码登陆管理服务器。
4.在 flash media server上开始你的应用程序。
5.在管理控制台中的调式列表中选择应用程序。
6.如果需要的话,点击 stream 按钮来查看正在播放的流的列表。
7.点击其中的一个流。
8.点击播放流的按钮。
9 一个弹出窗口被打开,然后流被播放。
10.如果需要的话,点击 Shared Objects按钮来查看应用程序的 Shared Objects。
11,点击一个 Shared Objects。
12,点击 close debug按钮来结束调式会话。
 
1.5.2测试和调试客户端脚本
  要测试客户端的脚本,使用 trace()语句将每个过程点显示在显示器上。在 flash  CS3 的
窗口 > 输出面板里面会显示结果(这里以 Hello  World 的应用程序为例):
 
  要调试客户端的脚本,使用 Flash  Cs3 里面的调试菜单来设置断点,跟踪函数等诸如此
类的事情,你可以在窗口>调试面板中检查脚本的状态。
1.6 配置一个应用程序
1.6.1复制服务器端文件使起在Flash media server上生效
连接到 flash media server上的应用程序必须在服务器上注册,这样服务器就能知道那些
试图连接的人是谁。要在服务器上注册一个应用程序,在主应用程序的文件夹下创建一个对
应与这个应用程序的文件夹,默认的主应用程序的文件夹是在 Flash  Media  Server
3/applications,要创建一个应用程序的实例,在这个应用长须的文件夹下创建一个字文件夹
(例如 Flash Media Server 3/applications/exampleApplication/instance1)。把服务器端的脚本复
制到服务器的 applicatiuon 目录下使其生效:
RootInstall/applications/YourApplicationName
 
RootInstall/applications/YourApplicationName/scripts
 
RootInstall/applications/YourApplicationName/YourInstanceName/
 
RootInstall/applications/YourApplicationName/streams/YourInstanceName/
默认的,当一个应用程序被请求时 flash media server检查上述的目录。
注释:要移动一个正在运行的应用程序,将文件复制到新的位置,然后在管理控制台中重启
这个应用程序。
 
 
  例如,要运行在 RootInstall/documentation/samples 目录下的 Stream 的范例,首先,你
需要将 Streams 文件夹复制到 application 目录,如下 RootInstall/applications/Streams。要运
行 StreamLength 的范例,需要将 StreamLength 文件夹复制到 application 目录,如下
RootInstall/applications/StreamLength。确保文件爱你加包含 main.asc 文件和 streams 子文件
夹。(as和 Fla 是源文件,不需要在这些目录里面,swf文件可以在任何地方运行)。
1.6.1.1打包服务端的文件
  Flash media server  包括一个命令行文档编译器‐‐‐far.exe,这个使你可以将服务器端的脚
本打包到一个 FAR 文件里面,FAR 文件使一个档案文件就像一个 ZIP文件,用来简化配置。
你也可以使用文档编译器来将服务器端脚本编译到字节码(扩展名为.ase 的文件)来加速请
求加载一个应用程序实例的时间。
  一个打的应用程序会包含很多个存储在不同地方的服务器端脚本文件。一些文件在应用
程序的目录下,另一些被分散在服务器配置文件定义的脚本库路径里面。简化你的媒体应用
程序的开发,你可以将你的服务器端的 JS,asc,ase 文件打包在一个自己包含的 flash media
server文档文件(FAR 文件)。
FAR 文件使一个包含主要的脚本文件(可以是 main.js,  main.asc,  main.ase,
applicationName.js,  applicationName.asc,  or  applicationName.ase 文件)和主要脚本文件关联
到的其他的脚本文件。
  运行文档编译器来创建脚本包的语法如下:
c:\> far ‐package ‐archive <archive> ‐files <file1> [<file2> ... <fileN>]
下表描述了可用的打包 FAR  文件的命令行的操作
操作符  描述
‐archive archive  制定档案文件的名字有.far 后缀名
‐files file1 [ file2 ... fileN ]  制定要包含在档案文件里面的文件列表.  致
少有一个文件。
注释:如果主要脚本关联到的其他脚本在子目录下,在文档文件里面必须包含层级关系。
要实现层级关系,Adobe建议你在主要脚本的目录里面运行 FAR。
 
 
1.6.2复制客户端文件到一个网络服务器
  将 SWF文件复制到网络上的服务器。
2 流服务
2.1 使用实况服务
2.1.1关于实况服务
实况服务就是在 flash media server上创建一个发布点。你可以使用 Flash media encoder
来捕捉,编码并且向实况服务流式实况发布视频,并且可以在范例客户端或 FLVPlayback 组
建里面播放视频。你也可以建立你自己的应用程序来捕捉视频,你自己的客户端应用程序来
播放视频。
下列的实况视频资源可以向实况服务发布视频:
 
Flash Media Encoder 2.0
注释:只有 Flash Media Interactive Server 和  Flash Media Development Server  支持 Flash
Media Encoder  的附加。
Flash Media Interactive Server and Flash Media Development Server(查看从服务器到服
务器的发布)
一个定制的 Flash Player 应用程序用来录制音频和视频
 
2.1.2测试实况服务
1.在电脑上连接一个摄像头。
2.打开 Flash Media Encoder 点击开始。默认的 Flash Media Encoder 会向同一台电脑的默
认实况发布点发布流,rtmp://localhost/live,发布的流的名字是 livestream。
3.双击RootInstall/samples/applications/live/livetest.html文件在浏览器里打开客户端应用
程序来观看实况流
要使用 FLVPlayback 组建作为客户端,设置连接路径的参数为发布点和流的名字的 URL:
(rtmp//localhost/live/livestream,默认)。并且将 isLive 参数设置为 true。
 
 
2.1.3修改实况服务
1,复制 RootInstall/applications/live 文件夹并给它一个新的名字,例如 live2.在这个例子
中,新的实况服务在 RootInstall/applications/live2 路径下
你可以按照需要创建很多实况服务的实例。
2.打开 fms.ini 文件(在 RootInstall/conf目录下)添加一个新的条目来设置新服务的路径,
例如 LIVE2_DIR = C:\Program Files\Adobe\Flash Media Server 3\applications\live2.  
3.打开RootInstall/applications/live2  目录下的Application.xml文件改变虚拟路径条目为:
<Streams>/;${LIVE2_DIR}</Streams>.
4,重启 Flash media server
5.客户端可以用 rtmp://flashmediaserver/live2/streamname这个 URL 来连接到发布点。如
果客户端是 FLVPlayback 组建,设置连接路径参数为发布点的 URL 加上流的名字,设置
isLive 参数为 true.
 
2.1.4取消实况服务
  将所有的实况服务文件夹移动到 application 文件夹外面。
 
 
2.2 使用视屏点播服务
2.2.1关于视频点播服务
  视频点播服务(video  on  demand)服务让你不要创建任何的应用程序或配饰服务器就
能流式的播放录好的视频。你可以使用 Flash CS3 和 flash8 的 FLVPlayback 组建做客户端。将
Mp4,FLV 和MP3 文件复制到 vod application 的媒体文件下就可以向客户端传播流了。
2.2.2测试视频点播服务
  1.做下列事情之一:
   双击RootInstall/samples/applications/vod/vodtest.swf文件在一个单机的flash player
打开一个客户端
   双击 RootInstall/samples/applications/vod/vodtest.html 文件在浏览器里面打开一个
客户端。
  2.点击 go.
  3(可选)要播放其他版本的范例文件,从 pop‐up菜单里面选择文件然后点击 go。
 
2.2.3修改视频点播服务
  1,复制 RootInstall/applications/vod 文件夹并给它一个新的名字,例如 vod2.在这个
例子中,新的视频点播服务在 RootInstall/applications/vod2 路径下
你可以按照需要创建很多实况服务的实例。
2.打开 fms.ini 文件(在 RootInstall/conf目录下)添加一个新的条目来设置新服务的路径,
例如 VOD2_DIR = C:\Program Files\Adobe\Flash Media Server 3\applications\vod2.  
3.打开RootInstall/applications/vod2  目录下的Application.xml文件改变虚拟路径条目为:
<Streams>/;${VOD2_DIR}</Streams>.
4,重启 Flash media server
5.将编码好的媒体文件放到你在 fms.ini 里面定义好的文件夹下(在这个例子里面就是
C:\Program Files\Adobe\Flash Media Server 3\applications\vod2\media)。媒体文件现在可
以通过 rtmp://flashmediaserver/vod2/filename 这个URL 得到。
注释:你不需要详细说明这个 URL 的子文件夹;meida 目录已经在 fms.ini 文件里面被
你设置了。
 
2.2.4取消视频点播服务
将所有的视频点播服务文件夹移动到 application 文件夹外面。
 
2.3 为流服务创建客户端
2.3.1创建一个客户端应用程序
  以提供的范例客户端代码为例( RootInstall/samples/applications/live  and
RootInstall/samples/applications/vod),按照需要而修改它。
  客户端的视频点播和实况服务可以使用出了相面两个以外的所有 flash player 的特性
  录制实况流(NetStream.publish("streamName", "record")).
  远程调用 shared objects(SharedObject.getRemote()).
2.3.2使用FLVPlayback组件
  你可以使用 flash 8 和 flash cs3 里面的 FLVPlayback 组件当作视频点播和实况服务的客户
端。将连接路径参数设置成流的 URL,如果式连接到实况服务的话设置 isLive 参数为 true.
2.3.3连接到一个流服务
  流服务希望写入的 URI 是一下的格式
rtmp://hostName/serviceName/instanceName/[formatType:]fileOrStreamName。
hostName:是 Flash Media Server的域名。
serviceName:或者是 vod 或者是 live。
InstanceName:如果客户度连接到默认的实例,你可以或者选择或者忽略实例的名字或
者使用_definst_.如果客户端连接到一个你已经创建的一个实例,比如 room1,就使用那个名
字。
formatType:是一种支持的格式 flv:, mp3: or mp4:.  如果没有特别标注的话默认的格式是  
flv:.
fileOrStreamName:或者是一个文件名(例如 my_video.mp4) ,或者是一个路径名(例如
subdir/subdir2/my_video.mp4)。如果文件是 FLV 或 MP3 万恶渐渐的话,你不要特别标注文件
格式,如果是一个 Mp4 文件,你必须标注格式,例如
rtmp://www.examplemediaserver.com/vod/ClassicFilms/mp4:AnOldMovie.mp4.

2.3.4允许从特别制定的域的连接
  默认的,客户端可以从任何地方连接到实况和视频点播服务。要限制连接客户端的域,
编辑服务的 application 文件夹下的文本文件
找到 the RootInstall/applications/live  或 RootInstall/applications/vod  folder 做下列事情之

要为 SWF客户端添加一个域,编辑 allowedSWFdomains.txt 文件
要为 HTML客户端添加一个域,编辑 allowedHTMLdomains.txt 文件。
这些 TXT 文件抱恨了添加域的细节信息。
3 开发媒体应用程序
  Adobe? Flash? Media Interactive Server的视频应用程序可以是视屏点播或者是实况视频
的应用程序。视屏点播应用程序是从服务器发送编码完的视频流,比如电视节目,商业或个
人录制的存储在服务器上是视频。一个组织可能有大量的视频档案或最近正在拍摄视频。视
频可以是短的片段(0‐30 秒),长片段(30 秒到 5 分钟),或非常长的片段(5 分钟到小时
级别的长度)。
  实况视频应用程序将视屏从服务器流式的发给用户或从用户发送给服务器然后再到其
他用户。实况视频是一个实况事件的典型应用,像公司会议,教育,体育事件和音乐会或者
持续的发送,被电视台和电台使用。你可以使用可以从 Adobe.com 上得到的 Adobe  Flash
Media Encoder 来编码和流传播实况视频。
3.1 连接到服务器
3.1.1NetConnection类
  在一个客户端可从 flash media server播放音频和视频之前,它必须连到服务器。连接的
需求会被服务器的应用程序的实例接受或拒绝,连接消息会被发送回客户端。一个应用程序
接受连接请求,一个在客户端和服务器端可用的连接就产生了。
  NetConnection 类连接客户端到以个服务器的应用程序的实例。在最简单的例子里面,
你可以通过创建一个NetConnection对象的实例然后用应用程序实例的URI来调用connect()
方法:
var nc:NetConnection = new NetConnection();
nc.connect("rtmp://localhost/HelloServer");
 
流处理网络连接上音频,视频和数据的流动。一个 NetCOnnection 对象就像一个从客户端到
服务器,或从服务器到客户端的传输音频,视频和数据流的管道。一旦你创建了
NetConnection 对象,你可以在上面附加一个或多个流。
 
一个流可以承载不止一种类型的连接(音频,视频和数据)。然而,一个流只流向一个方向,
从服务器到客户端或从客户端到服务器。
 
许多流可以使用服务器和客户端之间的 NetConnection 对象
 
 
A. Flash Media Server B.  单个数据流  C. NetConnection D. Flash Player, AIR, or Flash Lite 3 客户
端。
 
3.1.2应用程序的URI
连接到应用程序的 URI 可以是相对路径或绝对路径,有以下语法(括弧里面的是可选的):
protocol:[//host][:port]/appname/[instanceName]
组成部分  举例  描述
protocol:  rtmp:  协议是用来连接到 Adobe
Flash Media Server,  全城就是
Adobe  Real‐Time  Messaging
Protocol.  可能的值为  are
rtmp,  rtmpe,  rtmps,  rtmpt,
and  rtmpte.  要看跟多信息,
查看技术前言
 
//host  //www.example.com
//localhost
本地或远程计算机的主机名.
连接到一个作为服务器和客
户端的同一台电脑,  使用
//localhost  或者忽略  //host
标识符。
:port  :1935  连接到  Adobe  Flash  Media
Server的端口号,如果协议是
rtmp,  默认的端口号是  1935
你不需要制定特殊的端口号
/appname/  /sudoku/  当你的应用程序配置完成后
RootInstall/applications 的子
目录的名字。你可以在
fms.ini( 在
RootInstall/conf/fms.ini).配置
文件里面为你的应用程序的
目录指定其他位置  。
instanceName  room1  客户端连接的应用程序的实
例,比如,一个聊天室的应用
程序会有许多聊天的房间:
chatroom/room1,
chatroom/room2,等等
如果你不指定一个实例的名
字,客户端就连接默认的实
例,名叫_definst_.
URI 里面唯一需要的部分是 protocol  和 application name,如下所示
rtmp://www.example.com/sudoku/
在下面的例子里面,客户端是作为服务器的同一台电脑,这是在你开发和测试应用程序时很
常见的:
rtmp:/sudoku/room1
 
3.1.3helloserver应用程序
  你可以在安装的根目录下的 documentation/samples/HelloServer 目录下找到 HelloServer
应用程序。这个简单的 Flash 应用程序显示两个按钮,可以让你创建和关闭与服务器的连接。
输出窗口显示了连接状态的信息。
 
运行应用程序
最简单的运行这个范例的方法时将它安装到作为服务器的同一台电脑上。
1.在 flash media  server的安装根目录的 documentation/samples  目录下复制HelloServer
文件夹。
2.在服务器的application文件夹RootInstall/applications/HelloServer下创建一个文件夹来
注册应用程序。
3.(可选)要想在一个不同的电脑上运行 sample,打开 HelloServer.as 文件,编辑下面
的行,把你自己服务器的 URL 加进去
nc.connect("rtmp://localhost/HelloServer");
要知道如何构造一个 URL 查看《连接到服务器》。
设计 Flash 用户界面
范例已经建号并且包括在一个 ZIP文件里面,然而,这些说明告诉你怎么重创建它这样
你就可以建造你自己的并且向里面添加东西。
  1.在 Adobe Flash CS3 Professional 里面,选择文件  >  新建  > Flash 文件  (ActionScript 3.0),
点击 Ok.
  2.选择窗口>组件打开组建面板。
  3.点击按钮组件并将它拖到舞台。
  4.在属性查看器中,点击属性条目。选择 MovieClip 作为实例行为,并且将实例的名称
里面填入 connectBtn。
  5 点击参数条目,然后选则 Label,将按钮的 Label设置为 Connect。
  6.拖动第二个按钮组件到舞台。
  7.将第二个按钮的实例名称设置为 closeBtn,Label为 Close。
  8.保存 FLA 文件,命名为 HelloServer.fla。
 
创建客户端脚本
  你可以在Flash Media server的安装根目录下的documentation/samples/HelloServer目录
里找到完整的 Actionscript 范例,名为HelloServer.as。当你开发 Actionscript3.0 的代码。查看
ActionScript 3.0 语言和组件参考。
  1.在 Adobe Flash CS3 Professional 里面选择文件>新建>Actionscript 文件,然后点击 OK。
  2.以大写字母开头并且以.as 为扩展名来命名和保存这个 ActionScript 文件。比如
HelloServer.as。
  3.返回到 FLA 文件,选择文件>发布设置。点击 flash 条目然后设置。
  4.在文档类的框框里面,输入 HelloServer。点击绿色的检查标记来去确保类文件存在。
  5.点击 OK,然后再点击 OK。
  6.再 ActionScript 文件里面声明包。如果在 FLA 的同一目录下保存的 actionscript 文件,
不要使用包名,例如:
package {
}
然而如果你在 FLA 文件的目录的子目录下保存了 as文件,包名必须匹配你的 Actionscript 文
件的目录,例如:
package samples {
}
  7.在包里面,导入你需要的类:
import flash.display.MovieClip;
import flash.net.NetConnection;
import flash.events.NetStatusEvent;
import flash.events.MouseEvent;
  8.在导入语句后,创建类的声明。在类里面定义 NetConnection 类型的变量:
public class HelloServer extends MovieClip {
     private var nc:NetConnection;
}
  确保类是扩展了 MovieClip 类的(貌似 Sprite 类更好)
  9 编写构造函数,为每个按钮注册事件侦听。
public function HelloServer() {
//  为两个按钮注册 mouse clicks事件侦听
  connectBtn.addEventListener(MouseEvent.CLICK, connectHandler);
     closeBtn.addEventListener(MouseEvent.CLICK, closeHandler);
}
使用 addEventListener()  来调用一个名叫 connectHandler()事件处理函数,处理当 Connect
按钮被点击时的事件。同样的,当 Close 按钮被点击时调用 closeHandler()。
  10.编写 connectHandler()函数,当用户点击 Connect 按钮时通过这个函数来连接到服务
器:
public function connectHandler(event:MouseEvent):void {
     trace("Okay, let's connect now");
     nc = new NetConnection();
     nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     nc.connect("rtmp://localhost/HelloServer");
}
  在 connectHandler()中,添加了一个 NetConnection 对象的 netStatus 事件的事件侦听。
然后通过调用NetConnection.connect()和使用正确的URI连接到服务器上的应用程序的实例。
这个 URI 连接到一个名叫 HelloServer 的应用程序实例,它就在这台既作为服务器又作为客
户端的电脑上。
  11.编写 closeHandler()函数来定义当用户点击 Close 按钮时的行为。
public function closeHandler(event:MouseEvent):void {
     trace("Now we're disconnecting");
     nc.close();
}
这是明确的调用 Close()来关闭和服务器端的连接的最好的实践。
  12.编写 netStatusHandler()函数来处理 NetConnection 对象返回的 netStatus对象。
public function netStatusHandler(event:NetStatusEvent):void {
     trace("connected is: " + nc.connected);
     trace("event.info.level: " + event.info.level);
     trace("event.info.code: " + event.info.code);
     switch (event.info.code)
     {
         case "NetConnection.Connect.Success":
             trace("Congratulations! you're connected" + "\n");
             break;
         case "NetConnection.Connect.Rejected":
             trace ("Oops! the connection was rejected" + "\n");
             break;
         case "NetConnection.Connect.Closed":
             trace("Thanks! the connection has been closed" + "\n");
             break;
         }
}
一个netStatus对象包含了一个info对象, info对象包含了表述连接状态的level和  code。  
3.1.3.1 理解连接消息
  当你运行范例,点击了 Connect 按钮时,一旦连接成功,你会看到这样的消息:
Okay, let's connect now
connected is: true
event.info.level: status
event.info.code: NetConnection.Connect.Success
Congratulations! you'r e connected
Connected 行是:true 显示了 NetConnection.connected 属性的值,意味这 Flash  Player
是否通过 TRMP协议连接到了服务器。下面两行描述了 netStatus 事件,NetConnection 对象
发送和报告了它的连接状态:、
event.info.level: status
event.info.code: NetConnection.Connect.Success
level 属性有两个值:status 或 error。code 属性描述了连接的状态。你可以在你的
netStatusHandler 函数里面检查不同的 code 的值,并相应的做出响应。在你创建流或在你的
应用程序里面做其他事情前都要检查确保连接成功。
  同样的,当你点击关闭按钮时,你可以看到下面的信息:
Now we're disconnecting
connected is: false
event.info.level: status
event.info.code: NetConnection.Connect.Closed
Thanks! the connection has been closed。
 
3.2 管理连接
3.2.1连接状态的code  
  一旦一个在服务器和客户端的连接被建立,它可以会有很多种原因被打断。可能是网络
瘫痪,可能是服务被停止,或者连接可能被服务器或客户端关闭。任何在连接状态种的改动
都会产生一个 netStatus事件, netStatus 有 code和 level 两个属性来描述改变。这是一个 code
和 level 的集合。
Code  Level  含义
NetConnection.Connect.Success  status  一个连接被成功的建立了
要查看完整的由 netStatus 事件返回的 code 和 level 值的完整了列表,可以查看
actionScript3.0 语言和组件参考里面的 NetStatus.Info。
当事件被返回,你可以通过 event.info.code  和  event.info.  level 来得到连接的 code 和
level。你也可以检查 NetConnection.connected 属性(是 true 和 false)来查看连接是否还存
在。如果连接不能被创建或变得不可用,你需要在应用程序的客户端采取一些行动。
3.2.2管理服务器端代码的连接
  一个应用程序可能也有服务器端的代码,一般是main.asc 或 applicationName.asc 文件来
管理试图连接的客户端(查看编写服务器端代码介绍)。
  服务器端有权使用 Client 对象(Client 对象代表了在服务器端的独立的客户端)和
Application 对象(Application 可以使你管理应用程序的实例)。在服务器端的代码里面,你
使用服务器端的 actionscript 和服务器端的信息对象(查看服务器端 actionscript 语言参考)。  
  在服务器端的代码里面,应用程序可以接受或拒绝客户端的连接,关闭应用程序,运行
其他任务来管理连接。当一个客户端连接上了,应用程序接受一个 application.onConnect 事
件。同样的,当客户端断开连接,应用程序接受到一个 application.onDisconnect 事件。
  要在服务器端管理连接,使从服务器端的 actionscript 的 application.onConnect()和
application.onDisconnect()开始的,技术服务器端的脚本总是有权使用client对象和application
对象。
3.2.3管理连接的范例应用程序
  这个范例展示了如何分别从客户端和服务器端的代码管理连接。
 
编写客户端代码
  在客户端代码里面,你需要检查特别连接的 code 并处理他们,只有在客户端接受到
NetConnection.Connect.Success 后才能创建实况流或者播放已经编码的流。的那个客户端接
受到 NetConnection.Connect.AppShutDown,所有的从服务器到客户端或者从客户端到服务
器的流被关闭。在那种情况下,关闭和服务器的连接。
注释:查看 SimpleConnectManage sample, SimpleConnectManage.as,  使用  ActionScript 3.0.写
的。
1,创建一个NetConnect 对象并且调用 connect()方法来连接到服务器。
  2,编写 netStatus 时间处理函数,在这里面,要检查特别的 connection 的 code,并且
对每个 code进行处理。
public function netStatusHandler(event:NetStatusEvent):void
{
     trace("connected is: " + nc.connected );
     trace("event.info.level: " + event.info.level);
     trace("event.info.code: " + event.info.code);
     switch (event.info.code)
     {
         case "NetConnection.Connect.Success":
             trace("Congratulations! you're connected");
             // create live streams
             // play recorded streams
             break;
         case "NetConnection.Connect.Rejected":
             trace ("Oops! the connection was rejected");
             // try to connect again
             break;
         case "NetConnection.Connect.Failed":
             trace("The server may be down or unreachable");
             // display a message for the user
             break;
         case "NetConnection.Connect.AppShutDown":
             trace("The application is shutting down");
             // this method disconnects all stream objects
             nc.close();
             break;
         case "NetConnection.Connect.Closed":
             trace("The connection was closed successfully ‐ goodbye");
             // display a reconnect button
             break;
         }
     }
运行代码
注释:这些说明可以应用月任何的 actionscript3.0 的范例,即便在这个向导里面没有 flash
用户界面。Actionscript3.0的代码的提供是为例方便你。
  1.检查客户端的代码来查看连接到哪一个应用程序:
nc.connect("rtmp://localhost/HelloServer");
  2. 在服务器上创建一个应用程序实例的路径来注册应用程序,例如
RootInstall/applications/HelloServer
  3,可选,或者,要使用一个你已经注册过的应用程序,改变 connect 中的 URI:
nc.connect("rtmp://localhost/MyApplication");
  4,在 Adobe  Flex  Builder  或者  有 Flex  Builder 插件  的 Eclipse  里面,创建一个名叫
SimpleConnectManage的 actionscript 项目(选择文件>新建>actionscript 项目然后根据向导一
步一步的做)。
  5 向项目中添加 SimpleConnectManage的范例文件
  6.选择 run>debug,在 debug 窗口中,在 project 项目中输入 SimpleConnectManage,在
Application file  中输入 SimpleConnectManage.as  ,点击 debug。
  7.关闭打开的空的应用程序的窗口,返回 Flex  Builder  or  Eclipse.,检查控制台窗口的消
息  。如果连接成功的话,你应开看到如下的输出:
connected is: true
event.info.level: status
event.info.code: NetConnection.Connect.Success
Congratulations! you're connected
[SWF]  C:\samples\SimpleConnectManage\bin\SimpleConnectManage‐debug.swf ‐  2,377  bytes
after decompression
 
3.3 编码的流
3.3.1播放编码的流
  Adobe  Flash  Media  Server一个最流行的用处就是将存储在服务器上的编码好的视频和
音频以流的方式传输到很多客户端。
  要播放编码的流,传入一个编码好的文件的 URI 给 NetStream.Play()方法,如下
ns.play("bikes");
  这行制定了你在通过 NetConnection.connect()连接到的应用程序上的一个较 bikes.flv 的
编码好的流。简单的来说,play()方法有四个参数,语法如下:
public function play( name:Object [,start:Number [,len:Number [,reset:Object] ] ]):void  
name  编码好文件的名字
start  播放的开始点之前的时间,以秒为单位
len  要播放的长度,以秒为单位
reset  是否清除在播放列表里面之前播放过的视频
 
这些参数在 actionscript3.0 语言和组件参考中的 NetStream.play()中有详细描述。
 
3.3.2捕捉视频的简单影像
  这个特征是你可以得到给定视频,包括音频的很小一段的简单影像,用作显示的目的。  
  Flash player 客户端被允许从被 Client.audioSampleAccess 和  Client.videoSampleAccess  属
性制定的流中得到数据,查看 actionscript3.0 语言和组件参考。
  要得到数据,调用在客户端调用 BitmapData.draw()  和 SoundMixer.computeSpectrum(),
查看 actionscript3.0 编程中的捕获声音输入。
注释:在播放器里面播放的流可以通过使用累计的下载或者 RTMP流来处理
 
3.3.3处理流中的元数据
  一个编码好媒体文件拥有通过服务器或其他工具编码进的元数据。Flash Video Exporter
utility (version 1.1 or  later)  是一个可以挖掘处理视频的长度,帧率和其他视频自身信息的工
具。其他的视频编码器挖掘不同的元数据集,或者你可以明确的添加你自己的元数据(查看
向实况流添加元数据)。
  NetStream 对象在客户端播放流,当流遇到原属据时就会发出 onMetaData 事件。要读
取元数据,你必须处理这个事件并且提取出包含元数据的 info 对象。例如,如果一个文件
被 Flash Video Exporter,编码,info 对象包含这些属性
长度  视频的长度
宽度  视频的宽度
高度  视频的高度
帧率  视屏被编码的帧率
在《向实况视屏中添加元数据》中有一个列表的属性名,Adobe 建议用户在从客户端传到服
务器的实况视频流中添加元数据。
3.3.4视频播放范例
  如果你已经创建了一个可以连续下载视频的 Flash 视频播放的界面,你可能使用了
FLVPlayback 组件来设计你的视频播放器的界面。这个指南使用不同的技术,用 Actionscript3.0
在舞台添加一个 Video 对象。
注释:这个指南里面使用了 Streams范例,Streams.as,在 sample ZIP文件里面。
要在 Flash 里面使用 FLVPlayBack 组件,查看 Adobe  Creative  Suite  3  Video  Workshop,
"Creating  a  Video  Application  with  Components"  和 The  HTML  tutorial,  "Creating  a  Video
Application with Components"
在 Flash 里面运行范例
要运行范例的最简单的方法就是在你的即是服务器,又是客户端的电脑上安装应用程
序。
1.在客户端的 sample 目录里面放置 Streams.as文件
2.在服务器端创建一个目录来注册应用程序:RootInstall/applications/Streams。
3.将 Stream 范例文件夹(包括 Stream.fla)复制到 Streams 应用程序的目录下,你英豪
又一个包含 the video file, bikes.flv:文件的名叫 streams/_definst_的文件夹。
4.(可选)要在不同的电脑上运行范例,打开 Streams.as然后编辑如下一行代码,在里
面加上你的服务器上的应用程序实例的 URI。
nc.connect("rtmp://localhost/Streams");
查看《连接到服务器》可以得到构造 URL 的细节。
  5.在 Flash Cs3 里面,打开复制到 Flash Media Server applications 的  Streams.fla 文件。
  6.选择控制>测试音影片。没有声音的视频就会播放,输出面板输出如下内容。
 
你可以看到随着流的播放和连接状态的改变而看到输出的变化。 NetStream.play()的调用引发
了 onMetaData 事件的发生,元数据就会在控制台窗口输出如下
metadata: duration=30 width=292 height=292 framerate=30
 
在 Flex里面运行范例
  1.在 Flex Builder  或者安装了 Flex Builder 插件的 Eclipse  里面打开 Stremes.as
  2.选择 Run > Debug,在 Project 里面选择 Stremes,在 Application 里面选择 Stremes.as。  
  3.点击 Debug。
    一个视频播放的应用程序的窗口打开。点击 FLexBuilder 的窗口来看输出信息,完整
的信息如下:
connected is: true
event.info.level: status
event.info.code: NetConnection.Connect.Success
Congratulations! you're connected
connected is: true
event.info.level: status
event.info.code: NetStream.Play.Reset
connected is: true
event.info.level: status
event.info.code: NetStream.Play.Start
metadata: duration=30 width=292 height=292 framerate=30
[SWF] C:\samples\Streams\bin\Streams‐debug.swf ‐ 3,387 bytes after decompression
connected is: true
event.info.level: status
event.info.code: NetStream.Buffer.Full
connected is: true
event.info.level: status
event.info.code: NetStream.Play.Stop
The stream has finished playing
connected is: true
event.info.level: status
event.info.code: NetStream.Buffer.Flush
handling playstatus here
connected is: true
event.info.level: status
event.info.code: NetStream.Buffer.Empty
 
编写一个主客户端的类
注释:用 Actionscript3.0 来看 Stremes 范例,Stremes.as
  1.创建一个 Acrionscrip3.0 的类。导入NetConnection,NetStreme类和其他你需要的类:  
package {
     import flash.display.Sprite;
     import flash.net.NetConnection;
     import flash.events.NetStatusEvent;
     import flash.net.NetStream;
     import flash.media.Video;
...
}
  2.创建一个新 Stremes类,在里面申明你需要的变量。
public class Streams extends Sprite
{
     var nc:NetConnection;
     var stream:NetStream;
     var playStream:NetStream;
     var video:Video;
...
}
3.定义 Stremes 类的构造函数,创建一个 NetConnection 对象,并且为它添加事件侦听
器,然后将它连接到服务器。
public function Streams()
     {
         nc = new NetConnection();
         nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
         nc.connect("rtmp://localhost/Streams");
     }
4.创建你的 netStatusHandler 函数(它会处理 NetConnection 和 NetStreme发出的事件)  
private function netStatusHandler(event:NetStatusEvent):void
     {
         trace("connected is: " + nc.connected );
         trace("event.info.level: " + event.info.level);
         trace("event.info.code: " + event.info.code);
         
         switch (event.info.code)
         {
             case "NetConnection.Connect.Success":
                  trace("Congratulations! you're connected");
                  connectStream(nc);
                 // createPlayList(nc);
                  // instead you can also call createPlayList() here
                  break;
             
             case "NetConnection.Connect.Failed":
             case "NetConnection.Connect.Rejected":
                  trace ("Oops! the connection was rejected");
                  break;
              
             case "NetStream.Play.Stop":
                  trace("The stream has finished playing");
                  break;
              
             case "NetStream.Play.StreamNotFound":
                  trace("The server could not find the stream you specified");  
                  break;
              
             case "NetStream.Publish.BadName":
                  trace("The stream name is already used");
                  break;
      }
}
要知道完整的可用的事件的 code 的列表,在 Actionscript3.0 语言和组件参考中查看
NetStatusEvent.info
1 创建 NetStreme对象,并且注册一个 netStatus侦听器
private function connectStream(nc:NetConnection):void {
     stream = new NetStream(nc);
     stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     stream.client = new CustomClient();
     ...
注意你要设置 client 属性为一个 CustomClient 类的实例。CustomClient 类是一个定义一
些特别的事件处理的需要你自己写的独立的类。
2.创建一个 Video 对象然后将它和流绑定
  video = new Video();
     video.attachNetStream(stream);
这里我们用 Actionscript3.0 创建了一个 Video 对象,你也可以通过拖动一个 Video 原件
到舞台上来创建它。
在 Actionscript3.0 里面,使用 Video.attachNetStreme(),而不是 actionscript2.0 里面的
Video.attachVideo()将 Video 对象和流绑定。
3.调用 NetStreme.Play来播放流并且通过 addChild 来将它添加到舞台:
...
     stream.play("bikes", 0);
     addChild(video);
}
如果你拖动一个 Video 原件到舞台上的话你就不需要调用 addChild()方法。
传递给NetStreme.play方法的流的URI和你传递给NetConnection.connect()的URI相关。  
 
编写一个客户端事件处理类
 
  你也需要编写一个 CustomClient 类,这个来包括了 onMetaData 和 onPlatStatus 事件的
处理器。在你调用 NetStreme.play()的时候你必须处理这些事件,但是你不能使用
addEventListener()方法来注册这些事件的处理器。
  1.在你的主的客户端的类中,在 NetStreme.client 属性中关联到一个新的类
stream.client = new CustomClient();
  2.创建一个客户端的类:
  class CustomClient {
}
  3.编写一个名为 onMetaData()的函数来处理 onMetaData 事件:
public function onMetaData(info:Object):void {
     trace("metadata: duration=" + info.duration + " width=" + info.width +  
         " height=" + info.height + " framerate=" + info.framerate);
}
  4.编写一个名为 onPlayStatus()的函数来处理 onPlayStatus 事件:
public function onPlayStatus(info:Object):void {
     trace("handling playstatus here");
}
在播放视频之前进行检查
在播放前使用 FLVCheck 工具来检查一个编码好的视频是否有错误。视频文件中的错误会阻
碍视频的正常播放。查看 Adobe Flash Media Server  配置和管理向导以获得更多信息。  
3.4 错误处理
3.4.1关于错误处理
  在你创建视频应用程序的时候,学习管理连接和流的艺术是非常重要的。再网络环境里
面,一个连接的尝试可能会应为很多原因而失败:
  1.在服务器和客户端的任何一段的网络瘫痪。
  2.尝试连接到服务器的 URI 不正确。
  3.服务器瘫痪或者繁忙。
  4.  已经到达最大连接数或最大带宽。
如果一个连接被成功的建立,你可以创建一个 NetStream 对象和视频流。然而,流可能会发
生错误。你会需要在显示器上显示当前的帧频,关心缓冲变空的信息,下载的范例视频和发
生错误的点或者处理一个没有被发现的流。
  你的应用程序需要侦听和处理连接和流的 netStatus 事件来得到反馈。在你测试和运行
你的应用程序的时候,你也可以使用管理控制台来充当很多连接和流事件的故障检修员。
 
3.4.2处理失败的连接
  如果一个连接不能被建立,在你创建 NetStream 对象或者其他任何对象之前你需要处理
netStatus 事件。你可能需要重试连接到服务器的 URI,询问用户重新输入用户名或密码,或
者尝试其他的动作。
  需要关心的事件的 code和要采取的行动如下:
Event  行动
NetConnection.Connect.Failed  向用户显示服务器连接失败的信息
NetConnection.Connect.Rejected  重新尝试连接服务器
NetConnection.Connect.AppShutDown  断开所有的流对象并关闭连接
注释:使用 SimplConnectManage 范例, SimpleConnectManage.as是用 Actionscript3.0 编写的。  
编写客户端的代码来处理 netStatus事件
创建一个 NetConnection 对象并且连接到服务器,然后,编写 netStatus事件的处理函数,在
里面,你检测每一个事件并且为你的应用程序合理的处理事件,例如:
public function netStatusHandler(event:NetStatusEvent):void
{
     trace("connected is: " + nc.connected );
     trace("event.info.level: " + event.info.level);
     trace("event.info.code: " + event.info.code);
     switch (event.info.code)
     {
          ...
          case "NetConnection.Connect.Rejected":
             trace ("Oops! the connection was rejected");
             // try to connect again
             break;
          case "NetConnection.Connect.Failed":
             trace("The server may be down or unreachable");
             break;
          case "NetConnection.Connect.AppShutDown":
             trace("The application is shutting down");
             // this method disconnects all stream objects
             nc.close();
             break;
         ...
     }
}
3.4.3处理没有找到的流
如果一个你的应用程序尝试播放是流没有被找到的话,一个 code 内容为
NetStream.Play.StreamNotFound 的 netStatus 事件发生。你的 netStatus 事件处理函数需要侦
查这个 code并且采取措施,例如为用户显示消息或者播放一个在默认地方的标准的流。
注释:使用 Streams 范例 Streams.as 使用 Actionscript3.0 编写。
编写客户端脚本
在你的 netStatus 事件处理函数中,检查 StreamNotFound 的 code 并且做出处理。
private function onNetStatus(event:NetStatusEvent):void {
     switch (event.info.code) {
         case "NetStream.Play.StreamNotFound":
             trace("The server could not find the stream you specified");  
             ns.play( "public/welcome.flv");
             break;
         ...
}
3.5 播放列表
3.5.1关于播放列表
一个播放列表就是一个要被播放的流的序列。服务器以连续的流的方式处理流的列表并
提供缓冲。这样当流改变时观看者就会没有终端的感觉。
  你可以在客户端的代码里面定义一个播放列表。要这么做的话,调用 NetStream.play()
方法并且指定流的名称作为 NetStream.play()方法的参数。 Play()方法在 Actioncsript3.0 语言与
组件参考和 Actionscript2.0 客户端语言参考附录中有详细的描述。
应为你是从一个 NetStream 对象调用的 play().并且一个 NetStream 对像是和一个
NetCOnnection 对象联系的,所有的在播放列表离的流都应该在同一个服务器上。
3.5.2创建一个客户端的播放列表
  这个播放列表使用存储在服务器上的流的名字。要改变播放列表,你需要在你的客户端
的应用程序的代码里面做出修改:
注释:使用 Streams 范例 Streams.as 使用 Actionscript3.0 编写。
  1.创建一个 NetConnection 对象,连接到服务器,并且添加一个 netStatus 事件处理函数。  
  2.创建一个 NetStream 对象,并且侦听 netStatus事件
private function createPlayList(nc:NetConnection):void {
     stream = new NetStream(nc);
     stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     stream.client = new CustomClient();
     ...
}
  3.将 NetStream 对象与 Video 对象绑定
     video = new Video();
video.attachNetStream(stream);
4.为 NetStream 对象定义一系列的 Play()方法
     stream.play( "advertisement", 0, 30 );
     stream.play( "myvideo", 10, ‐1, false );
     stream.play( "bikes", 0, ‐1, false );
     stream.play( "parade", 30, 120, false);
     addChild(video);
}
5.在你的 netStatus 事件处理函数里面处理 netStatus的 code
private function netStatusHandler(event:NetStatusEvent):void
{
     ...
     case "NetStream.Play.Stop":
         trace("The stream has finished playing");
         break;
     case "NetStream.Play.StreamNotFound":
         trace("The server could not find the stream");  
         break;
}
 
这个播放列表将要播放这些流:
一个编码好的叫 advertisement.flv,的流,从头开始播放,播放 30 秒
一个编码好的叫 myvideo.flv,的流,从第 10 秒开始播放,直到结束。
一个编码好的叫 bikes.flv,的流,从头开始播放,直到结束。
一个编码好的叫 parade.flv,的流,从第 30 秒开始播放,播放 2 分钟。

3.6 多个比特率的转换
3.6.1关于多比特率的转换
  Adobe Flash Media Server可以编码和传送 On2 V6和 Sorenson Spark 编码的视频。Flash
Player 8  和9支持着两种编码,Flash Player 7 只支持早些版本的 Sorenson Spark 编码。
 你可以在服务器上创建一个虚拟的目录来存放每一种格式的视频流的拷贝。这个使你的
应用程更具客户端的 Flash player 版本发送最高质量的内容。
考虑一个范例 A:一个用户想要播放一个流,他已经安装了 Flash Player 8,支持 On2  视
频。客户端的应用程序请求 HappyStream.flv文件,在连接到服务器后,Flash player 8决定了
Client.virtualKey 属性。virtualKey 属性指向 c:\streams\on2 目录,而不是默认的 c:\streams  目
录,于是服务器播放用 On2 编码的 HappyStream.flv 流。
3.6.2基于Flash player版本而发送流
在 Vhost.xml 文件里面如下编辑 VirtualKeys和  VirtualDirectory 条目
<VirtualKeys>
     <Key from="WIN 7,0,19,0" to="WIN 9,0,0,0">A</Key>
     <Key from="WIN 6,0,0,0" to="WIN 7,0,18,0">B</Key>
     <Key from="MAC 6,0,0,0" to="MAC 7,0,55,0">B</Key>
</VirtualKeys>
<VirtualDirectory>
     <Streams key="A">foo;c:\streams\on2</Streams>
     <Streams key="B">foo;c:\streams\sorenson</Streams>
     <Streams key="">foo;c:\streams</Streams>
</VirtualDirectory>
要查看跟多关于编辑Key  和Streams的信息,参看Adobe Flash Media Server配置和管理向导。  
3.7 侦测带宽
3.7.1关于侦测带宽
  可能确保最好的播放体验中最重要的一个因素就是更具用户的带宽来比配数据。一旦你
侦测到用户的带宽,你可以:
  1.选择一个适合用户带宽的比特率的视频。
  2.基于带宽来设置一个视频的缓冲的大小
  在 Adobe Flash Media Server里面,带宽侦测器被构建在服务器。型的带宽侦测叫 native
bandwidth  detection。它提供了很好的运行状态和 scalability。要使用 native  bandwidth
detection,确定带宽侦测可以被使用,并且编写一个客户端的代码来调用构建在 Adobe Flash
Media Server的函数。
你可以使用任何版本客户端的的 Actionscript 来使用 native bandwidth detection(ActionScript
2.0 and 3.0 的范例已经被提供了)。你不需要添加或改变任何服务器端的代码。
3.7.2Actionscript3.0的native bandwidth detection
  在客户端成功连接到服务器后客户端应该启动带宽侦测。要开始带宽侦测,调用
NetConnection.call(),传递制定的命令 checkBandwidth 给它,就不需要服务器端的代码了。
 
A 客户端 B 服务器
编辑 Application.xml
确保在 Application.xml里面带宽侦测是可以使用的:
<BandwidthDetection enabled="true">
默认的话带宽侦测是可以使用的,你可以使用 Application.xml 制定你的的应用程序或应用在
虚拟主机上的应用程序(细节请参看 Adobe Flash Media Server配置管理向导)。
编写客户端事件处理类
  创建一个 Actionscript3.0 的类来处理事件并且调用服务器上的带宽侦测。它必须实现
onBWCheck 和 onBWDone 函数
class Client {
     public function onBWCheck(... rest):Number {
         return 0;
     }
     public function onBWDone(... rest):void {
         var p_bw:Number;
         if (rest.length > 0) p_bw = rest[0];
             // your application should do something here
             // when the bandwidth check is complete
             trace("bandwidth = " + p_bw + " Kbps.");
     }  
}
要确保 onBWCheck 很熟返回一个值,再 onBWDone 里面编写一些应用程序逻辑,这个
类会变成一个你的主 Actionscript3.0 的客户端。
编写主客户端类
1.创建你的主 Actionscript3.0 的类,选择一个包名和类名:
package {
     import flash.display.Sprite;
     import flash.net.NetConnection;
     import flash.events.NetStatusEvent;
 
     public class Bandwidth extends Sprite
     {
     }
}
你将主类和 client 类创建在同一个文件里面。
2 在主类的构造函数里面,创建一个 NetConnection 对象,将 NetConnection 对象的 client
属性设置为一个 client 类的实例,然后连接到服务器.
private var nc:NetConnection;
 
public function Bandwidth()
{
     nc = new NetConnection();
     nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     nc.client = new Client();
     nc.connect("rtmp://localhost/FlashVideoApp");
}
3.在 netStatus事件处理函数里面,如果连接成功的话调用 NetConnection.call()方法,将
checkBandwidth 作为要执行的命令,null 作为 responder 对象传入方法。
public function netStatusHandler(event:NetStatusEvent):void
{
     switch (event.info.code)
     {
         case "NetConnection.Connect.Success":
             // calls bandwidth detection code built in to the server
             // no server‐side code required
             trace("The connection was made successfully");
             nc.call("checkBandwidth", null);
             break;
         case "NetConnection.Connect.Rejected":
             trace ("sorry, the connection was rejected");
             break;
         case "NetConnection.Connect.Failed":
             trace("Failed to connect to server.");
             break;
     }
}
注释 checkBandwidthI()方法属于服务器端的 Client 类
运行范例
要是在 Flash CS3 或 Flex Builder2 里面测试主类的话,你会看到如下的输出来显示你的客
户端的带宽:
[SWF] C:\samples\Bandwidth\bin\Bandwidth‐debug.swf ‐ 2,137 bytes after decompression
The connection was made successfully
bandwidth   = 7287
在这个例子里面,Client 类简单的显示了带宽的值,在你的客户端,你需要做出一些动
作,如基于你的客户端的带宽而指定一个编码好的视频流。
3.7.3Actionscript2.0的native bandwidth detection
  你也可以像在 Actionscript3.0 里面那样在 Actionscript2.0 里面使用 native  bandwidth
detection,以会定义叫 onBWCheck()和 onBWDown()的函数,你会调用 NetConnection.call()
传递 checkBandWdith 的函数名给它。
注释:使用 BandWidthAS2 范例,BandWidhtAS2.as 是用 Actionscript2.0 编写的。
编辑 Application.xml
确保在 Application.xml里面带宽侦测是可以使用的:
<BandwidthDetection enabled="true">
默认的话带宽侦测是可以使用的,你可以使用 Application.xml 制定你的的应用程序或应用在
虚拟主机上的应用程序(细节请参看 Adobe Flash Media Server配置管理向导)。
编写客户端事件处理类
1.定义名叫 onBWCheck()的事件处理函数来接受从服务器发送的数据:
NetConnection.prototype.onBWCheck = function(data) {
     return 0;  
}
这个处理函数必须返回一个值,但是它可能是任何的值,甚至 0.这个返回值是服务器指导数
据被接受了。
2、定义名叫 onBWDone()的事件处理函数,这个函数接受一个参数,将会以 kbps 的单
位来度量带宽。
NetConnection.prototype.onBWDone = function(bw) {
     trace("bw = " + bw + " Kbps");
}
当服务器完成了带宽的侦测,它会调用 onBWDone(),然后返回带宽的值。
 
1.  定义一个 onStatus 处理函数,如果连接成功的话就调用服务器端的 checkBandwidth
函数。
NetConnection.prototype.onStatus = function(info) {
     if (info.code == "NetConnection.Connect.Success") {
         this.call("checkBandwidth"); // tell server to start bandwidth detection
     }
}
2.创建一个 NetConnection 对象并且连接到服务器:
nc = new NetConnection();
nc.connect("rtmp://host/app");
3.7.4基于脚本的带宽侦测
  你可以不使用 native bandwidth detection,而是使用服务器端的脚本的带宽侦测,就像
一个 main.asc 文件,特别是在你想服用已有代码的时候。
  如果你使用边缘服务器的话,运行在最外部边缘的服务器端的 native  bandwidth
detection 就会减少从原服务器的加载,然而,如果你有一个边缘和原的服务器网络,服务
器端的带宽侦测就会是从原服务器到客户端的带宽而不是边缘服务器到客户端端的带宽。富
国在原服务器和边缘服务器之间存在时延的话,就可能会影响带宽的计算。
 
在原服务器和边缘服务器之间是时延会影响带宽的测量。
A 原服务器 B 边缘服务器 C 客户端
要进行服务器端的带宽侦测,你可以使用ADOBE提供的为带宽政策而写的main.asc,你可以
在Flash  cs3 提供的Samples.zip  文件里面的\ComponentsAS2\FLVPlayback文件夹下找到
main.asc文件,这些可以从www.adobe.com/go/learn_fl_samples下载。你可能也需要在你的
Actionscript3.0  客户端里面做一些修改(查看BandwidthServer.as (ActionScript 3.0)范例)。
编辑 Application.xml
确保在 Application.xml里面带宽侦测是可以使用的:
<BandwidthDetection enabled="false">
默认的话带宽侦测是可以使用的。
编写客户端事件处理类
1.如果你正在使用 native  bandwidth  detection(查看"ActionScript  3.0  native  bandwidth
detection"),你要创建至少两个类,一个是连接到服务器的主类和一个处理事件的类。
2.在事件处理类里面,需要定义onBWCheck和onBWDone函数, 就像在BandwithServer.as
里面的那样
class Client {
     public function onBWCheck(... rest):Number {
         return 0;
     }
     public function onBWDone(... rest):void {
         var p_bw:Number;
         if (rest.length > 0)  
             p_bw = rest[0];
         trace("bandwidth = " + p_bw);
     }  
}
确保 onBWCheck()返回值,onBWDone()包括你的应用程序逻辑。
3.8 侦测流的长度
3.8.1关于侦测流的长度
  服务器端的 Stream 类允许你侦测一个已经编码好的流的长度。Stream 类有一个静态的
方法‐‐‐length(),这个函数以秒为单位,返回音频或视频的流的长度。流的长度是被 Adobe
Flash Media  Server测量而返回的,不同于 onMetaData 返回的 duration,那个是由用户或工
具设置的。
  要用 Stream.length().你必须制定一个流的名字。这个可能是一个真实的流的名字,和在
应用程序使用的 NetConnection.connect()的 URI 相关,或者是一个虚拟的流名。
  要使用一个真实的流名称,对于一个在 RootInstall/applications/dailyNews/下的应用程
序,它的流在 dailyNews/streams/_definst_ subdirectory 下,像这样调用 Stream.length():
length = Stream.length( "parade" );      // FLV 文件
length = Stream.length( "mp3:parade.mp3" );      // fMP3 文件  
length = Stream.length( "mp4:parade.mp4" );      // MP4  文件
3.8.2虚拟的流名
  服务器上的流的名字通常不是唯一的,所以你也可以使用虚拟的流的名字。要使用虚拟
的流名,会有多个在不同物理目录下的同名的编码好的流。你可以通过改变在 Vhost.xml 里
面的<VirtualDirectory>和<VirtualKeys>条目来创建一个虚拟的流名。
  虚拟的流名就像一个原始的流名,但是可以映射到多个在服务器上的目录。在虚拟的流
名中,调用 Stream.length()就像用真实的流名:
//  这是一个虚拟的流名
length = Stream.length( "videos/parade" );
编辑 Vhost.xml
  一个虚拟的流名同时使用虚拟的关键字和虚拟的目录映射来辨别客户端。如果客户端在
URI 里面使用虚拟流名的话你只要创建一个虚拟的流映射就可以了。
  1. 在你的服务器的安装目录下找到 Vhost.xml 。默认情况下,它位于
RootInstall/conf/_defaultRoot_/_defaultVHost_.
  2.在流的元素里面添加一个虚拟关键字,例如
<Streams key="9">
  一个虚拟关键字就是选择要使用的流元素的映射。如果客户端尝试播放是流有一个关键
字匹配虚拟关键字,服务器就会使用虚拟映射。
  3.在虚拟目录和物理目录之间天界一个映射
<Streams key="9">videos;c:\data</Streams>
这个映射了所有有发送有虚拟关键字 9 的 URI 的请求流的客户端到物理地址 c:\data。流名
videos/parade映射到了物理地址 c:/data/parade.flv.
3.8.3得到流的长度
  这个范例展示了服务器如何侦测到流的长度
注释:使用 StreamLength 范例,main.asc(服务器端 Actionscript 脚本)和 StreamLength.as
(Actionscript3.0)。要运行范例,查看通用的说明《配置一个应用程序》
编写一个服务器端的代码
一个客户端可能需要重新获得存储在服务器上的流的长度,例如,如果一个一个
FlashCS3 的展示要显示视频的长度好让用户决定是否播放它。
要做这件事的话,要在服务器端定义一个方法来调用 Stream.length().在 onConnect 处理
函数里面做这件事请。
在 main.asc 里面,定义一个基于 client 对象的调用 Streams.length()的函数,在 onConnect
处理函数里面做这件事情:
  application.onConnect = function( client ) {
     client.getStreamLength = function( streamName ) {
         trace("length is " + Stream.length( streamName ));
         return Stream.length( streamName );
     }
     application.acceptConnection( client );
}
  编写主客户端类
  在主客户端类里面,你调用服务器端代码的 getStreamLength()方法,你需要创建一个
Responder 对象来处理回应。
var responder:Responder = new Responder(onResult);
这一行指明了 onResult()方法来处理结果。你也需要编写 onResult()函数,:
  1 在你的客户端代码里面,创建一个包,导入类,定义变量:
  package {
     import flash.display.Sprite;
     import flash.net.NetConnection;
     import flash.events.NetStatusEvent;
 
     import flash.net.NetStream;
     import flash.net.Responder;
     import flash.media.Video;
  ……
  1.创建一个叫 StreamLength 的新类:
    public class StreamLength extends Sprite
     {
         var nc:NetConnection;
         var stream:NetStream;
         var video:Video;
         var responder:Responder;
}
1.在 StreamLength 类的构造函数里面调用 NetConnection.connect()方法来连接服务器:
public function StreamLength()
{
     nc = new NetConnection();
     nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     nc.connect("rtmp://localhost/StreamLength");
}
1.添加一个 netStatus 事件处理函数来处理一个成功的连接,或被拒绝的连接或一个失败
的连接:
private function netStatusHandler(event:NetStatusEvent):void
{
     trace("connected is: " + nc.connected );
     trace("event.info.level: " + event.info.level);
     trace("event.info.code: " + event.info.code);
            
     switch (event.info.code)
     {
         case "NetConnection.Connect.Success":
             trace("Congratulations! you're connected");
          connectStream(nc);
          break;
          
         case "NetConnection.Connect.Rejected":
         case "NetConnection.Connect.Failed":
          trace ("Oops! the connection was rejected");
          break;
      }
   }
1.编写一个函数,当一个成功的连接被创建时就播放流。在函数里面,创建一个
Responder 对象来处理在 onResult()中返回的回应。然后条用 NetConnection.call()方法,指定
在服务器端的 getStreamLength()方法:
//  播放服务器端的一个编码好的流
private function connectStream(nc:NetConnection):void {
     stream = new NetStream(nc);
     stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     stream.client = new CustomClient();
 
     responder = new Responder(onResult);
     nc.call("getStreamLength", responder, "bikes" );
 
}  
2.编写 onResult()函数来处理由服务器端的 getStreamLength()函数返回的流的长度:
private function onResult(result:Object):void {
             trace("The stream length is " + result + " seconds");
             output.text = "The stream length is " + result + " seconds";
   }
编写客户端的事件处理类:
通常,在播放一个流的时候,要编写一个单独的类来处理处理onMetaData和onPlatStatus
事件:
class CustomClient {
     public function onMetaData(info:Object):void {
         trace("metadata: duration=" + info.duration + " width=" + info.width +  
         " height=" + info.height + " framerate=" + info.framerate);
     }
     public function onPlayStatus(info:Object):void {
         trace("handling playstatus here");
     }
}

3.9 动态缓冲流
3.9.1关于流的缓冲
缓冲一个流帮助确保视频平滑的播放视屏。缓冲可以管理在视频播放时候的带宽波动。
这些波动是由于网络连接,服务器加载的改变或新的工作在客户端被执行而产生的。
  要为用户创建最好的客户体验,在视频下载是显示下载进程和缓冲管理。你需要为不同
的用户设置不同的缓冲大小老确保最好的播放体验。一个选择就是政策用户的带宽(查看《带
宽侦测》)然后基于带宽来设置出示带宽。
  当流在播放是时候,你也可以侦测和处理 netSatatus事件。例如,当缓冲满了, netStatus
事件就会返回了 info.code 的值 NetStream.Buffer.Full.当缓冲空了,另一个有 code 值为
NetStream.Buffer.Empty的事件会产生。当流的数据播放完了,NetStream.Buffer.Flush 事件被
发出。你可以侦听这些事件然后设置缓冲尺寸,当缓冲空的话就吧尺寸设置小点,如果缓冲
满的话就设置大一点。
  注释:Flash Player 9 更新3 中当一个流停止是不再清除缓冲。这个允许观不要再浪费事
件就可以重新观看。当观看者正在观看一个节目时开发者也可以在代码里面使用
NetStream.pause()来缓冲数据,然后当主的视频开始时继续播放视频。要查看更多信息,在
Adobe Flash Media Server ActionScript 2.0  语言参考或者  the ActionScript 3.0  语言和组件参考
查看 NetStream.pause()条目
3.9.2处理缓冲事件
这个范例展示了如果去侦测缓冲事件,并且当事件发生时动态的调整缓冲事件。这里显
示高亮的代码,要看完整的范例,查看 Buffer.as范例文件。要运行范例,在配置应用程序里
面查看说明。
  要改变缓冲时间,使用 NetStream.setBufferTime()以秒为单位来设置。
ns.setBufferTime(2);
  对于最快的连接来说,两秒的缓冲是很合适的,对于慢的连接来说,10 秒比较适合。
编写主客户端类
1.创建一个 Actionscript3.0 类
2.在构造函数里面,创建一个 NetConnection 对象并且连接到服务器(查看 Flash Media Server
更目录下的 documentation/samples/Buffer 的 Buffer.as类):
nc = new NetConnection();
     nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     nc.connect("rtmp://localhost/Buffer");
1.编写 netStatus 时间处理函数,检查成功,失败,满的换从,空的缓冲等时间,并且更具
情况来设置缓冲的大小。
private function netStatusHandler(event:NetStatusEvent):void {
         switch (event.info.code) {
             case "NetConnection.Connect.Success":
                 trace("The connection was successful");
                 connectStream(nc);
                 break;
             case "NetConnection.Connect.Failed":
                 trace("The connection failed");
                 break;
             case "NetConnection.Connect.Rejected":
                 trace("The connection was rejected");
                 break;
             case "NetStream.Buffer.Full":
                 ns.bufferTime = 10;
                 trace("Expanded buffer to 10");
                 break;
             case "NetStream.Buffer.Empty":
                 ns.bufferTime = 2;
                 trace("Reduced buffer to 2");
                 break;
         }
     }
 
1.编写一个 custom 方法来播放流。在这个方法里面,设置一个初始化的缓冲时间,例如两

     private function connectStream(nc:NetConnection):void {
         ns = new NetStream(nc);
         ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
         ns.client = new CustomClient();
         
         video = new Video();
         video.attachNetStream(ns);
             
         ns.play( "bikes", 0 );
         ns.bufferTime = 2;
         trace("Set an initial buffer time of 2");
     
         addChild(video);
}    
 
编写客户端事件处理类
就像通常你播放流视频,编写一个实现 onMetaData()和 onPlayStatus()事件处理函数的独立的
client 类
public function onMetaData(info:Object):void {
         trace("Metadata:  duration="  +  info.duration  +  "  width="  +  info.width  +  "  height="  +
info.height + " framerate=" + info.framerate);
}
 
public function onPlayStatus(info:Object):void {
     switch (info.code) {
         case "NetStream.Play.Complete":
             trace("The stream has completed");
             break;
     }
}
这些事件处理函数在你调用 NetStream.play()的时候就需要了。
4 开发实况视频应用程序
Adobe Flash Media Server客户端可以从麦克风或摄像头上捕捉实况音频和视频,然后和
其他的客户端共享实况内容。这个特性可以允许你时事捕捉实况事件然后像观众们发布,或
者创建实况的音频和视频的会议。你可以使用 Flash Media Encoder 来捕捉视频并且实况的流
式的向 Flash Media Server传输。然而,由于 Flash Media Server只被 windows支持,你会想
要创建你自己的捕捉和流传输实况视频的客户端。
注释:这章的主要内容只可以在 Flash Media  Interactive  Server  和  Flash Media Development
Server上运行。因为 Flash Media Streaming Server 不支持服务器端的脚本。
4.1 捕捉实况的视频和音频流
4.1.1关于发布流和订阅流
  要从 Flash  player 向 Adobe  Flash  Media  Serve 发送视频,你必须使用
NetStream.attachVideo()将一个视频和流绑定。同样的,可以使用 NetStream.attachAudio().
来将一个音频和流绑定。
  要发布一个实况视频或者订阅一个已经编码好的流,要使用客户端的 NetStream类。如
果一个在服务器上编码好的视频已经可以使用,你的客户端想要接受它,就在客户端代码里
面创建一个 NetStream 对象,然后调用 NetStream.play().要向服务器发布一个视频,调用
NetStream.publish().
  publish()方法允许你通过制定 URI 来向你想要的流发布视频,URI 和服务器端的
application 文件夹有关。例如,一个客户端连接到
nc.connect("rtmp://www.example.com/TopNews/today"),然后它会使用一个相关的URI来制定
特别的流名字,例如,stream.publish("local",  "record"),,视频就会编码在一个名叫 local.flv
的文件,然后发布到 RootInstall/applications/TopNews/streams/today/local.flv
  客户端以订阅者的身份连接到 TopNews/today 的应用实例,然后在 NetStream.play()里面
指定 local.flv。
  一个创建流并且发送到服务器的客户端叫发布,一个创建流来接受内容的客户端叫订
阅,当同一个客户端同是发布和订阅时,它必须创建两个流,一个是输出流,一个是接受流。  
4.1.2实况流的范例
  要从客户端得到实况的音频和视频,使用 Camera, Microphone, ActivityEvent 类,当然,
也要有 NetStream  和  NetConnection。
  注释:使用 LiveStream 范例:LiveStream.as 和 main.asc(高亮代码被显示在这里)。对于
用户界面,使用 LiveStreams.fla 文件,也包括在范例米面,要运行范例,查看《配置应用程
序》里面的说明。
编写一个客户端代码
1.创建一个 ActionScript 类,在你的类里面,创建一个 NetConnection 对象,然后添加
netStatus 事件处理函数,然后连接到服务器。  
  2.添加 ActivityEven 处理函数
private function activityHandler(event:ActivityEvent):void {
         trace("activityHandler: " + event);
         trace("activating: " + event.activating);
}
3.编写发布实况流的函数。首先创建 NetStream,Camera,Microphone 的对象:
private function publishLiveStream():void {
     ns = new NetStream(nc);
     ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     ns.client = new CustomClient();
             
     camera = Camera.getCamera();
     mic = Microphone.getMicrophone();
...
}
4 向 Camera 和 Microphone 对象添加 ActivityEven 事件的侦听。然后,将摄像头和麦克
风的数据分别和和 Video 对戏和 NetStream对象绑定,然后调用 NetStream.publish():
if (camera != null){
                 
         camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
                 
         video = new Video();
         video.attachCamera(camera);
                 
         ns.attachCamera(camera);
     }
             
     if (mic != null) {
     
         mic.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
                             
         ns.attachAudio(mic);
     }
             
     if (camera != null || mic != null){
         // start publishing
         // triggers NetStream.Publish.Start
         ns.publish("localNews", "live");
         } else {
                 trace("Please check your camera and microphone");
         }
编写服务器端的代码
注释:LiveStream范例里面的服务器端的代码演示了多点发布的特征,这个特征使你向
额为的服务器重新发布,这样你可以向更加广大的观众广播。
1.编写application.onConnect()  和application.onDisconnect()函数 (查看Flash Media Server
安装更目录下的 documentation/samples/LiveStreams 目录下的 main.asc 文件) ,这些函数处
理客户端连接到服务器和断开和服务器的连接。
  2.编写 application.onPublish()函数,这个更函数在客户端发布流使被调用:
// called when the client publishes
application.onPublish = function(client, myStream) {
     
     trace(myStream.name + " is publishing into application " + application.name);
 
     // This uses the multi‐point publish feature to republish
     // streams to another application instance on the local server.
     if (application.name == "LiveStreams/_definst_"){
 
         trace("Republishing the stream into anotherInstance");
 
         nc = new NetConnection();
         nc.connect( "rtmp://localhost/LiveStreams/anotherInstance" );
         
         ns = new NetStream(nc);
3.在 application.onPublish()函数里面,为 NetStream.onStatus事件编写一个事件处理函数
     ns.onStatus = function(info) {
         trace("Stream Status: " + info.code)
         if (info.code == "NetStream.Publish.Start") {
             trace("The stream is now publishing");
         }            
     }     
NetStream 对象在服务器端的 ActionScript 里面有 onStatus 事件,这和 Actionscript3.0 里
面的 netStatus事件使等同的。
4.编写 application.onUnpublish()函数,当客户端停止发布时这个函数会被调用:
application.onUnpublish = function( client, myStream ) {
     trace(myStream.name + " is unpublishing"   );
}
4.2 录制实况视频
  当一个客户端向服务器发送实况视频,你可以给他们录制视频和存储视频的选项。使用
这个特性的应用程序有播客和其他为用户交流而建造的社交媒体程序。
  你的客户端应用程序要首先建立一个 NetStream 对象,并且吧 Camera 和 Microphone
对象和它绑定。
  要让用户录制实况视频,使用 NetStream.publish()方法,并且要给 howToPublish 参数传
入值"record",当你传入"record"后,文件就被存在服务器的包含应用程序的目录的一个子目
录下。你也可以传入"append"这个值给 howToPublish 参数来录制制品,并且将它添加到已经
存在的文件的末尾。
注释:所有的视频都是以 FLV 格式录制的。
按照《捕捉和流式的传输实况音频和视频》的做,但是在 NetStream.publish()里面使用使用
"record"参数如下:
ns.publish("public/myVacation", "record");
4.3.向实况流添加原数据
4.3.1关于元数据
  使用 Flash Media Server,你可以向一个实况视频流的开头添加数据消息。有用的数据可
能包括视频的长度,视频被录制的日期,录制者的名字等等。然可连接到服务器的客户端在
视频播放时都会接受的元数据。
  然而,如果你用一个不是你录制的视频来做实况流或者你想向流添加更多信息,你需要
自己设置元数据。你添加的元数据以数据关键帧的形式存在,每个数据关键帧可以包含很多
数据属性,如标题,高度和宽度。
  在客户端脚本里面调用 NetStream.send()方法就可以向实况流里面添加元数据。下面的
NetStream.send()就是添加一个数据关键帧的语法:
NetStream.send(@setDataFrame, onMetaData [,metadata ])
onMetaData 参数是当元数据被接受时的处理函数,你可以创建多个数据关键帧,每个
数据关键帧必须使用唯一的处理函数(例如 onMetaData1, onMetaData2等等)。
元数据的参数是一个包含被设置到流里面的元数据的Object (或者任何Object的子类)。
在 metadata对象里面,每一个元数据是一个有名字和一堆值的属性。你可以使用任何名字,
但是 Adobe 推荐你使用通用的名字,这样你设置的元数据就会容易阅读。
在客户端脚本里面调用 NetStream.send()方法来清空一个实况流里面的元数据。下面是
语法:
  NetStream.send(@clearDataFrame, onMetaData)
注释:要在服务器端脚本里面发送元数据,使用服务器端的 Actionscrip 脚本的 Stream.send()
方法
4.3.2实况流的元数据属性
Adobe 推荐的实况流的属性(不是录制的流)的名字被列在下表
元数据属性名称  数据类型  描述
lastkeyframetimestamp  Number  录制视频关键帧的最后录制
的时间表
Width  Number  视频的宽度,像素为单位
height  Number  视频的高度,像素为单位
videodatarate  Number  视频的比特率
audiodatarate  Number  音频的比特率
framerate  Number  视频录制时每秒的帧数
creationdate  String  文件的创建日期
createdby  String  文件的创建人
audiocodecid  Number  文件的音频编码器 ID,值为:
0 Uncompressed
1 ADPCM
2 MP3
5 Nellymoser 8 kHz Mono
6 Nellymoser
 
videocodecid
Number  文件的视频编码器 ID 值为 2
Sorenson H.263
3 Screen video
4 On2 VP6
5 On2 VP6 with transparency
Audiodelay  Number  音频解码器的延时介绍,以秒
为单位
4.2.4向实况视频添加元数据
注释:查看 LiveStream 范例,LiveStream.as 在 Flash  Media  Server 安装根目录下的
documentation/samples/LiveStreams 目录下
编写主的客户端类
1.创建一个 ActionScript 类
2.在构造函数里面,创建一个 NetConnection 对象,注册 netStatus事件侦听函数,连接
到服务器。
3. 编写一个发布实况视频的方法,使用 Camera 类和 Microphone 类和
NetStream.publish():
private function publishLiveStream():void {
     var ns:NetStream = new NetStream(nc);
     ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     var camera:Camera = Camera.getCamera();
     var mic:Microphone = Microphone.getMicrophone();
     if (camera != null && mic != null) {
         camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
         mic.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
         ns.attachCamera( camera );
         ns.attachAudio( mic );
         // start publishing
         // triggers NetStream.Publish.Start
         ns.publish( "local", "record" );
     } else {
         trace("Please check your camera and microphone");
     }
}
调用 NetStream.publish()时会激发 netStatus 事件,其 code 码为 NetStream.Publish.Start。你
可以选择广播实况流或者录制它。
4。添加 ActivityEvent 处理函数
private function activityHandler(event:ActivityEvent):void {
     trace("activityHandler: " + event);
     trace("activating: " + event.activating);
}
5,在你的 netStatus 事件处理函数里面,考虑 NetStream.Publish.Start 情况。当它发生
时,创建一个 metadata对象然后将它设置到实况流里面:
private function netStatusHandler(event:NetStatusEvent):void
{
     case "NetStream.Publish.Start":
         trace("Adding metadata to the stream");
         // when publishing starts, send the metadata
         var metaData:Object = new Object();
         metaData.title = "liveDJconcert";
         metaData.width = 400;
         metaData.height = 200;
         stream.send("@setDataFrame", "onMetaData", metaData);
         break;
         ...
}
编写客户端事件处理类
你也需要编写一个客户端事件处理类来处理 onMetaData 事件。
编写 onMetaData 处理函数,检查宽,高或其他通常使用的元数据
class CustomClient {
     public function onMetaData(info:Object):void {
         trace("width: " + info.width);
         trace("height: " + info.height);
     }
}
4.2.5为实况视频情况元数据
注释:查看 LiveStream 范例,LiveStream.as 在 Flash  Media  Server 安装根目录下的
documentation/samples/LiveStreams 目录下
编写主的客户端类
1.在你的 netStatus 事件处理函数里面,考虑 code值为 NetStream.Publish.Start 的情况。  
private function netStatusHandler(event:NetStatusEvent):void
{
     switch (event.info.code)
     {
         case "NetStream.Publish.Start":
         clearMetaData(ns);
     }
}
2 当 NetStream.Publish.Start 发生时,通过调用 NetStream.send()并且传入参数
@clearDataFrame 来情况流的元数据。
private function clearMetaData(ns:NetStream):void {
     this.ns = ns;
     ns.send("@clearDataFrame", "onMetaData");
     ns.attachCamera( camera );
     // clear the metadata
     ns.publish( "localNews" );
}
编写客户端事件处理类
你也需要编写一个客户端事件处理类来处理 onMetaData 事件。
编写 onMetaData 处理函数,检查宽,高或其他通常使用的元数据
class CustomClient {
     public function onMetaData(info:Object):void {
         trace("width: " + info.width);
         trace("height: " + info.height);
     }
}
4.2.6从实况视频中重新得到元数据
  要显示设置在实况流中的元数据,你需要处理 onMetaData 事件。处理实况流中的元数
据就和分析出被服务器或工具设置在编码好的文件中的元数据一样。
注释:查看 LiveStream 范例,LiveStream.as 在 Flash  Media  Server 安装根目录下的
documentation/samples/LiveStreams 目录下
编写客户端事件处理类
在你的主类之外创建一个 CustomClient 类。在这个类里面,编写 onMetaData 函数来得到一
个 info 对象,用下面的代码得到被设置为作为 info 对象一个属性的数据关键帧:
class CustomClient {
     public function onMetaData(info:Object):void {
         trace("width: " + info.width);
         trace("height: " + info.height);
     }
}
4.4 从服务器到服务器的发布
4.4.1关于多点发布
  错点发布允许客户端只通过一个客户端到服务器的连接向多个服务器发布视频。这个特
新允许你创建大规模实况广播应用程序,甚至其他服务器或订阅者在地球的不同位置。
 
使用多点发布来从服务器到服务器发布内容,甚至跨越不同的地方
A.  实况视频  B 服务器  1 (纽约市) C.服务器  2 (芝加哥)  和服务器 r3 (洛杉矶) D.  用户
这张图标显示了协调工作的应用程序的流程
1 一个客户端连接到在纽约的服务器 1 的应用程序来开始发布一个实况流。
2.服务器1的应用程序接受到一个application.onPublish,这个事件在main.asc文件处理。  
3.应用程序在 onPublish 事件处理函数里面创建了两个 NetStream 事件向在芝加哥的服
务器 2 和在洛杉矶的服务器 3 发送流。
4 服务器 1 通过 NetStream.publish()方法向服务器 2和服务器 3重新广播实况流。
5.连接到服务器 2 和服务器 3 的订阅者接收到同样的实况流。
6.当客户端停止发布时,应用程序接受到一个 application.onUnpublish 事件。
要使用多点发布,你需要在 main.asc 里面编写服务器端代码。
4.4.2多点发布
要使用多点发布,你需要编写客户端代码和服务器端代码。
注释:查看 LiveStream 范例,LiveStream.as 用(Actionscript3.0 编写)和 main.asc(用服务器
端 Actionscript 编写)在 Flash  Media  Server 安装根目录下的
documentation/samples/LiveStreams 目录下
编写客户端代码
1 在你的客户端里面,使用 NetStream.publish()和流的名字来发布一个流:
private function publishLiveStream():void {
     var ns:NetStream = new NetStream(nc);
     ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
     camera = Camera.getCamera();
     mic = Microphone.getMicrophone();
     if (camera != null && mic != null) {
         camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
         mic.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
         ns.attachCamera( camera );
         ns.attachAudio( mic );
         // start publishing
         // triggers NetStream.Publish.Start
         ns.publish( "localNews", "record" );
     } else {
         trace("Please check your camera and microphone");
     }
}
编写服务器端代码
在服务器的 main.asc 文件里面,定义一个 application.onPublish()事件处理函数来接受流
的名字,并且连接到远程的服务器。
// called when the client publishes
application.onPublish = function( client, myStream ) {
     trace(myStream.name + " is publishing" );
     nc = new NetConnection();
     nc.onStatus = function (info) {
         if (info.code == "NetConnection.Connect.Success") {
             ns = new NetStream(nc);
             ns.setBufferTime(2);
             ns.attach(myStream);
             ns.publish( myStream.name, "live" );
         }
     nc.connect( "rtmp://xyz.com/myApp" );
     }
 
}
通过调用 NetStream.publish()从你的服务器向远程服务器发布视频。
2 处理你使用的从你的服务器向远程服务器发布用的 NetStream 对象发出的事件:
ns.onStatus = function(info) {
     if (info.code) == "NetStream.Publish.Start") {
         trace("The stream is now publishing");
         trace("Buffer time is : " + this.bufferTime);
     }  
}
3.定义当你的客户端停止发布时的动作:
application.onUnpublish = function( client, myStream ) {
     trace(myStream.name + " is unpublishing"   );
}
5.开发社交的媒体程序
在流视频应用程序之外,Adobe  Flash  Media  Interactive  Server 和  Adobe  Flash  Media
Development Server可以运行社交媒体和其他时事商业应用程序。用户可以捕捉实况音频和
视频,将他们上传到服务器,然后和其他人一起分享。这些服务器的版本也提供远程的共享
对象用以同步许多用户之间的数据,这样的话就可以开发在线游戏。
  你可以使用服务器端的 Actionscript 脚本来连接到其他的系统,包括 Java2 企业版服务
器,web service,和 Microsoft.net 服务器。着个连接性允许应用程序使用服务的优势,如数
据库认证,从 web services和 e‐mail中时事更新。
  在这些高级的技术之外,社会媒体应用程序可以使用在《开发媒体以用程序》里面描述
的视频开发技术的优势。
  注释:这章的主要内容只可以在 Flash  Media  Interactive  Server  和  Flash  Media
Development Server上运行。因为 Flash Media Streaming Server 不支持服务器端的脚本。
5.1 共享对象
5.1.1关于共享对象
  使用共享对象来同步用户和存储数据。共享对象可以做从维持一个游戏频道的位子到广
播聊天的文字信息的任何事情。共享对象是你保持跟踪用户的时事动作。
  使用 Flash Media  Interactive  Server  或 Flash Media Development  Server,你可以创建和使
用远程的共享对象,共享对象可以在多客户端的应用程序之间共享数据。当一个用户做出了
一个更新服务器的共享对象的动作时,共享对象就会向所有用户发送改变信息。远程的共享
对象做为同步很多用户的一个网络中心,在这节里面的 SharedBall example,当任何一个用户
移动球,所有的用户都看到他在移动。
注释:Flash Media Streaming Server 不支持远程共享对象。
所有版本的服务器都支持本地共享对象,这个就相当域浏览器的 cookie。本地共享对象
存储于客户端的电脑里面,不需要一个服务器。
不管是本地还是远程的共享对象,都可以是零时的或永久的
一个零时的共享对象是由服务器端的脚本或者一个连接到共享对象的客户端而创建的。
当最后一个客户端断开连接或者服务器端的脚本不再使用共享对象了,它就被删除了。
  永久的共享对象会再所有的客户端断开连接甚至应用程序停止运行后还会保存数据。永
久的共享对象再应用程序下一次开始时还可以被使用。他们再应用程序的会话之间保存数
据。永久的共享对象被存储再客户端或服务器端的文件里面。
 
永久的本地共享对象
要创建永久的本地共享对象,调用客户端的 SharedObject.getLocal()方法。永久的本地共
享对象有扩展名.sol你可以再调用SharedObject.getLocal()的时候通过传递一个值给localPath
参数来为共享对象指定存储目录。通过指定一个本地存在的远程共享对象,你可以时很多再
同一域下的很多应用程序使用同一个共享对象。
远程永久共享对象
  要创建一个在服务器上永久存在的共享对象,在客户端代码的SharedObject.getRemote()
方法或者服务器端的 SharedObject.get()里面为 persistence 参数传入 true 值。这些共享对象
会以.fso 的扩展命名来命名,他们都存储在服务器上创建共享对象的应用程序的子目录下。
Flash Media Server会自动创建这些目录,你不需要为每个实例的名字创建一个目录。
远程和本地的永久共享对象
  你通过在调用你的客户端代码里面 SharedObject.getRemote()命令时给 persistence 参数
传入一个本地路径在服务器和客户端上创永久的远程共享对象。本地的永久共享对象是
以.sor 为扩展名的,被存储在客户端的制定的目录里面。远程永久的.fso 文件存储在服务器
上创建共享对象的应用程序的一个子目录下。
5.1.2远程共享对象
在你创建一个远程共享对象之前,首先创建一个 NetConnection 对象并且连接到服务器。一
点你有一个连接,使用 SharedObject类的方法来创建并更新远程共享对象。使用一个远程共
享对象的步骤的顺序如下:
  1.创建一个 NetConnection 对象并且连接到服务器:
nc = new NetConnection();
nc.connect("rtmp://localhost/SharedBall");
  这是最简单的连接到服务器的方法。在一个真实的应用程序里面,你需要给
NetConnection 对象侦听事件并且定义事件处理函数。要了解更多信息,查看 SharedBall 范
例。
2 创建一个远程共享对象。当连接成功后,调用 SharedObject.getRemote()在服务器上创
建一个远程共享对象。
so = SharedObject.getRemote("ballPosition", nc.uri, false);
次一个参数是远程共享对象的名称。第二个是你连接到的应用程序的 URI,并且这个
URI 必须是使用 NetConnection.connect()连接的 URI。最简单的方法来识别 URI 就是 nc.uri。
第三个参数制定远程共享对象是否为永久的。在这个例子里面,false 是指创建的是临时共
享对象。
3 连接到远程共享对象。一点共享对象被创建,在客户端使用 NetConnection 对象来连
接到共享对象
so.connect(nc);
你也需要给共享对象发出的 sync 事件添加侦听
so.addEventListener(SyncEvent.SYNC, syncHandler);
4.在客户端同步远程共享对象。同步远程共享对象需要两步。第一步,当一个独立的客
户端发生一个变化或者设置一个 data 的值,你需要更新远程共享对象。第二步,更新所有
其他的连接到这个共享对象的客户端
a.当客户端发出改变是要更新远程共享对象,使用 setProperty():
so.setProperty("x", sharedBall.x);
你必须使用 setProperty()来更新共享对象的值。远程共享对象有一个报刊属性和值的
data 属性。然而在 Actionscript 里面你不能如下这样直接编写值
so.data.x = sharedBall.x; //  你不能这么做。
b.当共享对象被更新,它会发出一个 sync 事件。通过读取共享对象的 data 属性台同步
其他客户端。
sharedBall.x = so.data.x;
这个通常在 sync 事件处理函数里里面执行,就像 SharedBall 范例里面的那样。
5.1.3SharedBall范例
  SharedBall 范例创建了一个临时的远程共享对象。它相当域一个对用户的游戏,当一个
用户移动球的时候,球也会在其他用户那边显示移动。
注释:使用 SharedBall 范例文件(SharedBall.as, SharedBall.fla, SharedBall.swf)在 Flash Media
Server安装根目录下的 documentation/samples/ SharedBall  目录下
 
运行应用程序
1.在服务器上创建一个 SharedBall 文件夹来注册一个应用程序:
RootInstall/applications/SharedBall
2  在 Flash Media  Server的安装根目录下的 documentation/samples/SharedBall 文件夹里面打
开 SharedBall范例
3.在浏览器里面打开 SharedBall.swf  文件
4.在另一个浏览器窗口里面打开另一个 SharedBall.swf。
5 移动一个里面的球,看另外一个。
编写客户端代码
确保你看过 SharedBall.as范例文件,这里的步骤都是比较重要的而已:
1.在 Flash CS3 里面,创建一个 Actionscript 文件
  2.创建一个 MovieClip 的子类
public class SharedBall extends MovieClip {...}
  这个类必须扩展 MovieClip 类,因为在 FLA 文件里面 sharedBall 原件是一个影片剪辑原

3.创建一个构造函数。在里面添加事件侦听和连接到服务器。
public function SharedBall()
     {             
         nc = new NetConnection();
         addEventListeners();
         nc.connect("rtmp://localhost/SharedBall");
     }
 
  4.为 netStatus,mouseDown,mouseUp,和 mouseMove 事件添加侦听:
private function addEventListeners() {
         nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
         // sharedBall  是在 FLa 里面定义的
         sharedBall.addEventListener(MouseEvent.MOUSE_DOWN, pickup);
         sharedBall.addEventListener(MouseEvent.MOUSE_UP, place);
         sharedBall.addEventListener(MouseEvent.MOUSE_MOVE, moveIt);
}
5.在你的 netStatus 处理函数里面,当连接成功后创建一个远程共享对象(你也需要创建
连接被拒绝或者连接失败的处理函数,这些在范例 AS文件里面都有)。连接到共享对象并且
添加 sync 事件侦听
switch (event.info.code)
{
     case "NetConnection.Connect.Success":
         trace("Congratulations! you're connected");
             so = SharedObject.getRemote("ballPosition", nc.uri, false);
             so.connect(nc);  
             so.addEventListener(SyncEvent.SYNC, syncHandler);
             break;
             ...
}
6.当一个用户移动鼠标时,使用 setProperty()来设置远程共享对象上的球的位置的改变:  
function moveIt( event:MouseEvent ):void {
     if( so != null )
     {
     so.setProperty("x", sharedBall.x);
     so.setProperty("y", sharedBall.y);
     }
}
当远程共享对象被更新,它就会发出 sync 事件
7,创建一个sync 事件处理函数来更新所有客户端上球的位置:
private function syncHandler(event:SyncEvent):void {
     sharedBall.x = so.data.x;
     sharedBall.y = so.data.y;
}
8,你可以读取 so.data 的值,但是你不能写它。
5.1.4向多用户广播消息
一个远程共享对象可以允许客户端或服务器使用 SharedObject.send()方法向所有连接到
共享对象的客户端发送消息。Send()方法可以被用作文字聊天的应用程序,例如,所有订阅
你的共享对象的客户端都会受到你的消息。。
1.创建一个 SharedObject.send()方法调用的函数。
private function doSomething(msg:String):void {
     trace("Here's the message: " + msg);
}
2.调用 SharedObject.send()来广播消息:
so = SharedObject.getRemote("position", nc.uri, false);
so.connect(nc);  
so.send("doSomething", msg);
5.2 允许或拒绝对资源的使用
5.2.1关于使用控制
  当用户使用服务器时,默认的,他们有完全的使用权来使用所有的流和共享对象。然而,
你可以使用服务器端的脚本来创建一个动态的共享对象和流的使用控制列表。你可以控制对
共享对象,流有读取,写入,创建等使用权的人。
  当一个客户端连接到服务器,服务器端脚本被传入一个 Client 对象。没一个 Client 对象
有读取权和写入权等属性。你可以使用这些属性来控制每个连接的使用权限。
5.2.2实现动态使用控制
  Client.readAccess 和 Client.wrtieAccess 属性有字符串的值,这些字符串可以有很多值,
这些值由分号分开,例如
client.readAccess = "appStream;/appSO/";
client.writeAccess = "appStreams/public/;appSO/public/";
默认的,readAccess和 writeAccess被设置为/,这就意味客户端有对每一个流和共享对象的使
用权。
允许对流的使用权
在 main.asc 添加一个 onConnect()函数来指定一个服务器上的目录的名字:
application.onConnect = function(client, name) {
     // give this new client the same name as passed in
     client.name = name;
 
     // give write access
     client.writeAccess = "appStreams/public/";
 
     // accept the new client's connection
     application.acceptConnection(client);
}
这个 main.acs文件同一了所有的以 appStreams/public.开头的 URI 的使用权。
拒绝流的使用权
在 main.asc 添加一个 onConnect()函数,在函数里面将 client.wrtieaccess 的值设置为””;
application.onConnect = function(client, name) {
     ...
     // deny write access to the server
     client.writeAccess = "";
}
定义对共享对象的使用权
在 main.asc 添加一个 onConnect()函数,在函数里面指定共享对象的名字,习惯上使用同样
的名字
application.onConnect = function(client, name) {
     ...
     client.writeAccess = "appSO/public/";
}
这个给与了客户端对于以 appSO/public/开头的 URI 的共享对象以写的权限。
5.3 鉴别客户端
5.3.1使用Client对象的属性
当一个客户端连接到一个应用程序,服务器创基恩一个包含客户端信息的 Client 对象,并且
将它传递给服务器端 Actionscript 的 application.onConnect()处理函数。你可以编写使用 Client
对象属性的服务器端代码,并且使用那些值来证实客户端连接的合法性。
application.onConnect = function( pClient ) {
     for (var i in pClient) {
         trace( "key: " + i + ", value: " + pClient[i] );
     }
}
检查客户端的 IP信息
在 main.asc 里面,检查 client.ip 的值,如果需要的话,拒绝客户端的连接请求
if (client.ip.indexOf("60.120") !=0) {
     application.rejectConnection(client, {"Access Denied"} );
}
检查原始的 URL
在 main.asc 里面,检查 client.referrer 的值是否在一个需要被拒绝使用的 URL 列表里面。确
保 SWF 文件是从你希望的地方连接到服务器。如果找到一个匹配的,就拒绝客户端的连接
请求
referrerList = {};
referrerList["http://www.example.com"] = true;
referrerList["http://www.abc.com"] = true;
 
if (!referrerList[client.referrer]) {
     application.rejectConnection(client, {"Access Denied"} );
}
5.3.2使用唯一的关键码
1.在客户端的 Actionscript 脚本里面,创建一个唯一的关键码,在下面的代码里面,将本地
电脑的时间和一个随机数相连而得到一个唯一关键码
var keyDate = String(new Date().getTime());
var keyNum = String(Math.random());
var uniqueKey = keyDate + keyNum;
2.将关键码发送到请求连接的服务器上:
nc.connect("rtmp://www.example.com/someApplication", uniqueKey);
3.下面的 main.asc 文件在连接请求里面寻找唯一关键码。如果关键码被遗失或者已经被使用
了,连接就被拒绝。通过这种方法,如果一个冒名顶替着要重新播放连接,重新播放的尝试
就会失败
replayclientKeyList = new Object();    // holds the list of clients by key
 
application.onConnect = function( pClient, uniqueKey ) {
     if ( uniqueKey != undefined ) {     // require a unique key with connection request
         if ( clientKeyList[uniqueKey] == undefined ) {    // first time ‐‐ allow connection
             pClient.uniqueKey = uniqueKey;
             clientKeyList[uniqueKey] = pClient;
             this.acceptConnection(pClient);
         } else {
             trace( "Connection rejected" );
             this.rejectConnection(pClient);
         }
     }
}
5.3.3使用访问插件
一个访问插件在一个请求传给 Flash Media Interactive Server之前将其截取。你可以使用任何
形式的认证来编写一个访问插件。要了解更多信息,参阅 Adobe Flash Media interactive Server
插件开发指南。
5.3.4使用Flash player版本
你可以通过接受连接中的用户代理字符串来保护你的内容被没有运行 Flash  player 的客户端
访问。用户代理字符串辨别了平台和 Flash player 的版本,例如:
WIN 8,0,0,0
MAC 9,0,45,0
有两种方法来使用这些字符串
虚拟关键字:配置服务器来基于 Flash player 客户端而重新映射流。要看更多信息,参阅《多
比特率的转换和虚拟关键字》
Client.agent 使用服务器端的 Actionscript 向来严格测试连接
remapapplication.onConnect = function( pClient ) {
     var platform      = pClient.agent.split(" ");
     var versionMajor = platform[1].split(",")[0];
     var versionMinor = platform[1].split(",")[1];
     var versionBuild = platform[1].split(",")[2];
}
 
// output example
// Client.agent:   WIN 9,0,45,0
// platform[0]:    "WIN"
// versionMajor:   9
// versionMinor:   0
// versionBuild:   45
5.3.5验证连接的SWF文件
你可以配置服务器,在允许客户端连接到应用程序之前验证客户端的 SWF 文件的真实
性。
验证SWF文件阻止那些通过自己编写SWF来尝试访问你的资源的人。 SWF验证被Flash Player
9 Update 3 或更高版本所支持。要查看跟多信息,参阅配置和管理指南。
5.3.6 允许和拒绝从特定域的连接
如果你知道要连接的合法用户的域,你可以讲那些域放到白名单里面,同样,你可以把
非法的域放到黑名单里面
你可以在Adaptor.xml文件里面输入静态的域名类表,要了解更多信息,参阅Adobe Flash
Media Server配置和管理指南
你也可以在你自己的服务器端的代码和文件里面保存这个列表,在下面的范例里面,一
个名叫 bannedIPList.txt 的文件里面包含了一个被排除的IP列表,它可以被很灵活的编辑
function getBannedIPList() (
     var bannedIPFile = new File ("bannedIPList.txt") ;
     bannedIPFile.open("text","read") ;
     application.bannedIPList = bannedIPFile.readAll();
     bannedIPFile.close() ;     
}
 
application.onAppStart = function() {
     this.blockINT = setlnterval(getBannedIPList, 30000);
     getBannedIPList();
     for (var index=O; index<bannedIPList.length; index++) {
         var currentIP = this.bannedIPList[index];
         if (pClient. ip == currentIP) {
             this.isIPOK = false;
         }
     break;
     }
 
     if (isIPOK) this.acceptConnection(pClient);
     else this.rejectConnection(pClient);
}
除此之外,你可以创建一个服务器端的代码来检查一个特别的域的连接是否来的太快
application.VERIFY_TIMEOUT VALUE = 2000;
 
Client.prototype.verifyTimeOut = function() {
     trace (">>>> Closing Connection")
     clearInterval(this.$verifyTimeOut);
     application.disconnect(this);
}
 
function VerifyClientHandler(pClient) {
     this.onResult = function (pClientRet) {
         // if the client returns the correct key, then clear timer
         if (pClientRet.key == pClient.verifyKey.key) {
             trace("Connection Passed");
             clearInterval(pClient.$verifyTimeOut);
         }
     }
}
 
application.onConnect = function( pClient ) {
     this.acceptConnection( pClient );
 
     // create a random key and package within an Object
     pClient.verifyKey = ({ key: Math. random () });
     
     // send the key to the client
     pClient.call("verifyClient",
         new VerifyClientHandler(pClient),
         pClient.verifyKey );
 
     // set a wait timer
     pClient.$verifyTimeOut = setInterval(pClient,  
                                       $verifyTimeOut,  
                                       this.VERIFY_TIMEOUT_VALUE,  
                                       pClient);
}
 
application.onDisconnect = function(pClient) {
     clearInterval(pClient.$verifyTimeOut);
}
5.4 用户验证
5.4.1使用外部资源来进行用户认证
对于限制用户,可以通过请求认证信息(用户名和密码)并且使用诸如数据库,LDAP 服务
器或其他确认服务来很轻松的完成。
1.SWF支持在连接请求中的用户认证信息
客户端可以在客户端的脚本里面提供用户名/密码的令牌。
var sUsername = "someUsername";
var sPassword = "somePassword";
 
nc.connect("rtmp://server/secure1/", {username:sUsername, password:sPassword} );
2. Flash Media Server 通过第三方的系统确认用户
你可以使用下列的服务器端Actionscript的类来调用外部资源:WebService, LoadVars, XML  类,
NetServices  (连接到一个Flash  Remoting  网关).要查看这些类的更多信息,参见服务器端
Actionscript 言参考。要知道 Flash  Remoting 更多信息,参见 语 的
http://www.adobe.com/go/learn_fms_flashremoting_en.
load("NetServices.asc");      // for Flash remoting
load("WebServices.asc");      // for SOAP web services
 
pendingConnections = new Object();
 
application.onConnect = function( pClient, pUsername, pPassword ) {
 
     // create a unique ID for the client
     pClient.FMSid = application.FMSid++;
 
     // place the client into a pending array
     pendingConnections[FMSid) = pClient;
 
     if (pUsername!= undefined && pPassword !=undefined) {
         // issue the external call (3 examples below)
         loadVars.send("http://url?login=" + pUsername + ?password" +  
                     pPassword + "?FMSid"+FMSid);
 
         webService.authenticate(FMSid, pUsername, pPassword);
 
         netService.authenticate(FMSid, pUsername, pPassword);
     }
 
// the result handler (sample only, you will have to customize this)
// this command will return a true/false and the FMS client id
Authenticate.onResult = { }
3.   Flash Media Server接受或拒绝连接
如果认证信息是合法的,   Flash Media Server会接受连接;
loadVars.onData = function ( FMSid, pData ) {
     if (pData) {
         application.acceptConnection( pendingConnections[FMSid] );
         delete pendingConnections[FMSid];
     } else {
         application. rejectConnection ( pendingConnections[FMSid] );
     delete pendingConnections[FMSid];
     }
}
5.4.2使用令牌认证
这个技术是一个用户名/密码形式的认证,令牌可以通过基于客户端的属性而确包正确。
控制流如下:
1.客户端 SWF 从第三方请求一个认证令牌。
2.第三方返回一个认证令牌。
3.客户端在发送连接请求是一起将令牌发出
4. Flash Media Server通过第三方系统确认令牌
5. Flash Media Server接受连接。
posted @ 2011-05-05 10:40  Marksion  阅读(5554)  评论(0编辑  收藏  举报