关于Flash Media Server
原 Flash Communication Server 已經正式改名為 Flash Media Server.
Flash Media Server 2.0 的最新消息
http://macromedia.breezecentral.com/p37828859/
1,運行多個應用程序和主機更加穩定
2,支持更多用戶連接
3,數據緩存功能
4,更好的集群和負載均衡
5,增強高質量大文件視頻回放
6,改進的管理和監視工具
7,服務器將記錄更多更詳細的log信息
8,XML接口的服務器管理和監視
9,用戶自定義的訪問控制
10,自動檢測播放器.
11.數據支持加密傳輸
12,增強的API:
-服務器端支持XML sockets
-服務器端支持Web Services
-服務器端支持JPG流
-服務器端支持文件系統訪問(有安全沙盒限制)
Macromedia公司發布Macromedia Flash Media Server 2,這款服務器軟件成功組合了傳統流媒體功能和靈活的開發環境,用于創建和交付創新的互動式媒體應用。作為最近發布的Macromedia Flash Professional 8和Flash Player 8的補充,Flash Media Server 2使Flash Platform成為用于跨各種瀏覽器和操作系統創建、提供互動式富媒體應用的領先的解決方案。目前,領先的媒體、娛樂、電信、零售和廣告等行業用戶迅速采用Macromedia Flash Video,用于為全世界數百萬瀏覽者提供定制的、無縫的視頻體驗。
Flash Platform提供了一流的網絡視頻體驗。如今,絕大部分的網絡視頻需要利用一大批眼花繚亂的可選件和下載件才能展示,如果把最新發布的Flash Media Server 2與無所不在的Flash Player相結合,就能跨眾多平臺、各種連接速率和瀏覽器,可靠地提供流暢、即時的視頻體驗。發布者也可以把視頻集成到自己的網站和應用當中,而且可以完全控制回放、互動和品牌建立,獲得無縫體驗。
Macromedia高級副總裁、總經理Tom Hale說:“FlashPlatform是向互聯網上最廣泛的受眾提供網絡視頻和豐富媒體應用的最佳方式,就集成到網絡體驗當中的流視頻而言,目前還沒有比Flash Media Server 2更好的選擇。”
Flash Media Server 2是在大規模部署環境下提供錄制和實況FlashVideo的基礎,如視頻點播、實況網絡廣播、MP3媒體流、視頻博客和視頻/音頻聊天等應用。新版本引入了可擴展的新款Edge-Origin服務器,這個企業級就緒的可選架構簡化了負載均衡、故障替換和集群工作,從而能夠確保流式傳輸富交互體驗具有更高的可靠性和擴展性,即使是在流量高峰期間。Flash Media Server 2擁有獨特的可編程流媒體環境,包括性能可靠的應用編程接口(API),對媒體流、資產和特性(如定制互動、用戶驗證和帶寬檢測)實現精確的代碼控制,從而提供真正不同的用戶體驗。Flash Media Server 2視頻體驗充分利用了Flash Player 8中新的高質量視頻編解碼器,并具有自動檢測客戶端的帶寬連接、相應調整媒體流的功能。
Scripps Networks公司的Flash開發人員Tim O'Hare說:“在HGTVPro,我們的主要挑戰是,開發出生動而豐富的寬帶視頻應用,來滿足最終用戶和廣告客戶不斷提高的要求。通過使用Macromedia Flash Media Server 2和Macromedia Flash Professional,我們獲得了前所未有的能力,來創建并向我們的廣大受眾展示了HGTVPro一系列的互動內容。現在,Flash Media Server 2提供了Flash Video流式傳輸方面的增強功能新選項,讓我們可以部署更廣泛的內容,更重要的是,這些內容可以通過多種平臺來瀏覽。憑借極具互動性、創新性的控制功能,Flash Video提供了其他任何媒體播放器根本不可能提供的網上內容。”
Flash Media Server可以在標準的Windows或Linux服務器上運行,可以與現有的數據庫、萬維網和數據服務集成。進一步拓展的擴展功能使用戶能夠管理基于XML的媒體元數據、訪問本地系統資源、控制日志和報告,以便與現有的媒體吸收和管理系統更緊密地進行集成。
原 FlashCommunication Server 正式改名為 Flash Media Server
FMS2 還是不給屏幕共享功能,我們可以通過第三方軟件實現的.
VH Screen Capture Driver
或
Camtasia Studio
The scalable media server for streaming interactive mediaapplications
Macromedia Flash Media Server 2 software offers the uniquecombination of traditional streaming media capabilities and a flexibledevelopment environment for creating and delivering innovative, interactivemedia applications to the broadest possible audience.
發布地址:http://www.macromedia.com/software/flashmediaserver/
免費開發版下載:http://www.macromedia.com/cfusion/tdrc/index.cfm?product=flashmediaserver
FMS2組件更新
免費開發版下載
?
FLASH COM學習筆記1
第一章
內容:本人學習FlashCom Develop的閱讀筆記,陸續提供,僅供參考,不作它用
心得作者:Liu21st
第一章? 開始
一、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 代碼. 給第一行添加下面代碼
???? #i nclude 'Netdebug.as'
???? 以便進行NetConnection 調試(ps.新版的FlashCom Server已經不包含netdebug.as文件,需要安裝FlashRemote )
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_的實例,可以對不同的實例建立不同的共享對象
01 : // One instance of application 'support'
02 : first_nc = new NetConnection();
03 : first_nc.connect('myserver.mydomain.com/support/session1');
04 : first_so = SharedObject.getRemote('CustomerInfo', first_nc.URI, false);
05 : first_so.connect(first_nc.URI);
06 :
07 : // Another instance of application 'support'
08 : second_nc = new NetConnection();
09 : second_nc.connect('myserver.mydomain.com/support/session2');
10 : second_so = SharedObject.getRemote('CustomerInfo', second_nc.URI, false);
11 : 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和兩者)
FLASH COM學習筆記: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();
?
FLASHCOM 學習筆記:3 數據流
?
第二章 Flash Communication Server結構概要
Flash Communciation Server 包含了server端(由一些asc文件組成)和client端(swf文件)
server端和client端的數據傳輸通過Real-Time Message Protocol (RTMP)進行實時交流,web server通過http服務把內容提供給client端,實現模式如下圖:
450) {this.resized=true; this.width=450;}" border=0>
多用戶可以連接到同一個應用程序Application
450) {this.resized=true; this.width=450;}" border=0resized="true">
Flash Communciation Server實際上為不同的用戶之間提供了相互交流的通道。
基于客戶/服務器模式的application,服務器端主要負責數據的傳輸,由客戶端發送請求,服務器端執行數據查詢和計算并返回結果值給客戶端,通常需要保持長時間的連接。
Flash Communciation Server提供了兩種方法控制用戶的更多交互:數據流和共享對象.
數據流是指在服務器端和客戶端同步傳遞的音頻、視頻和其它數據的信息流,數據流可以通過簡單的發布和訂閱方式實現。一個發布的數據流可以實時的被看到(如視頻聊天室),
450) {this.resized=true; this.width=450;}" border=0>
也可以被錄制下來以后播放。
450) {this.resized=true; this.width=450;}" border=0>
錄制的數據流被存為Flash Video (FLV) 格式,其中可以包含文本、音頻和視頻等信息。當然你也可以把存在的通過第三方的軟件錄制的視頻和音頻文件轉換為flv格式的文件。
?
FLASH COM學習筆記. 4:共享對象
?
共享對象
在FlashCom開發過程種可以使用兩種共享對象:本地和遠程共享對象。
本地共享對象可以看作是Flash cookie,可以在用戶的本地機器存放用戶數據,其本身為Flash player提供,可以無須FlashCom Server的支持。
遠程共享對象是由FlashCom Server來管理的,提供了信息和數據的同步,以及數據的存儲。
Flash客戶端連接、提交給遠程共享對象,并且與服務器端保持同步。信息數據還可以發布到所有連接到遠程共享對象的客戶端,并通過應用程序的session或臨時文件持續。更多的信息請參考共享對象類。
450) {this.resized=true; this.width=450;}" border=0resized="true">
連接外部數據源
根據FlashCom的數據流和共享對象提供的交流模型,FlashCom Server還可以和外部數據源交互,例如web 服務器、關系數據庫,甚至其它的FlashCom Server應用程序。例如,你可以寫一個服務器端的腳本文件來連接一個web服務器或ColdFusion應用程序來接收一串用戶名和電話號碼的列表,然后把查詢結果寫入共享對象。詳細的方法后面的章節會描述。
450) {this.resized=true; this.width=450;}" border=0resized="true">
創建和開發應用程序的流程
你可以使用FlashMX創作工具來創建應用程序的客戶端組件,生成的swf文件提供了應用程序的用戶界面,其中也包含了與FlashCom Server連接和控制的as腳本。
服務器端則需要相關的應用程序目錄,其中包含了運行客戶端所需要的asc腳本,提供多個客戶端之間邏輯控制和數據交換。
450) {this.resized=true; this.width=450;}" border=0resized="true">
在開發應用程序的過程種,客戶端程序需要發布到合適的位置以保證應用程序的正常運行,這通常要結合Web Server,如html、php、asp等,因為FlashCom Server采用rtmp協議,所以web server并非必須,你可以直接在swf文件中執行,但不推薦這樣做。
服務器端程序(包含asc、flv等文件)需要放置到正確的應用程序目錄下面。
450) {this.resized=true; this.width=450;}" border=0resized="true">
如果你是一個FlashCom Server管理員,你可以使用管理控制臺來配置FlashCom server、設置系統安全、監視使用情況,停止和重啟server,還可以添加用戶。這需要用來第一章提到的應用程序管理器和管理工具
450) {this.resized=true; this.width=450;}" border=0resized="true">
?
FLASH COM學習筆記.5.應用示例
?
/*
+-------------------------------------------------------------------
| FlashCom 閱讀筆記
| 版本: 1.0
| 作者: Liu21st 晴天的魚
| 郵箱: Liu21st2002@msn.com
+-------------------------------------------------------------------
| 版權聲明: Copyright◎ 2004-2005 世紀流年版權所有
| 個人筆記未經允許,嚴禁轉載
| 主頁: http://blog.liu21st.com
+-------------------------------------------------------------------
*/
下面內容主要講述如果用如何通過客戶端連接服務器,怎樣訪問共享對象,以及調用遠程方法等。
當用戶使用客戶端的swf文件連接服務器時,服務器會加載應用程序,如果沒有運行就創建實例。服務器端接受連接之后,產生一個新的客戶端對象回應該客戶端應用程序,執行指定的服務器端腳本。客戶端需要做的是初始化數據流和共享對象等
連接流程
當客戶端開始連接服務器后,服務器端會調用onAppStart方法(確保應用程序實例已經處于運行狀態)
接下來,服務器端會回調客戶端定義的onConnect方法,該方法的邏輯決定了是否接受該連接請求。當客戶端斷開連接的時候,會調用服務器端的onDisconnect方法;當應用程序結束后,會調用onAppStop方法
450) {this.resized=true; this.width=450;}" border=0resized="true">
遠程方法調用
在連接成功之后,客戶端可以調用服務器端組件定義的方法,服務器端也可以調用客戶端組件中的方法。
每一個連接到服務器端的應用程序都作為一個服務器端的客戶對象實例,每一個客戶端的實例對象都可以通過NetConnect對象調用遠程服務器的方法,然后服務器端可以回應并返回值給客戶端。下面的圖表示了在客戶端調用服務器端方法并獲取返回值的方法:
450) {this.resized=true; this.width=450;}" border=0resized="true">
從服務器端回調客戶端的方法
從服務器回調客戶端的方法比較類似于上面所說的。在客戶端,可以給NetConnect對象的實例自定義方法,在服務器端可以利用client.call的方式調用客戶端的方法。圖示即為從服務器調用客戶端并返回值的方法。
450) {this.resized=true; this.width=450;}" border=0resized="true">
共享對象的使用
共享對象簡化了在多用戶之間共享數據的開發工作,一個Flash 客戶端要獲取遠程共享對象可以通過 SharedObject.getRemote來指定連接,
然后通過SharedObject.connect連接遠程共享對象,一旦連接成功,服務器端會發送同步信息給各個連接的客戶端,客戶端使用SharedObject.onSync來保持同步,下面的圖簡單描述了其使用過程。
450) {this.resized=true; this.width=450;}" border=0resized="true">
?
FLASH COM學習筆記.6.對象概述
?
/*
+-------------------------------------------------------------------
| FlashCom 閱讀筆記
| 版本: 1.0
| 作者: Liu21st 晴天的魚
| 郵箱: Liu21st2002@msn.com
+-------------------------------------------------------------------
| 版權聲明: Copyright◎ 2004-2005 世紀流年版權所有
| 個人筆記未經允許,嚴禁轉載
| 主頁: http://blog.liu21st.com
+-------------------------------------------------------------------
*/
第三章使用對象
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與FlashComServer建立連接,并且使用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')
FLASH COM學習筆記.7.理解共享對象
理解共享對象
共享對象可以存儲任何Flash支持的數據類型。就存放位置來說,共享對象可以分成存在客戶端計算機的本地型,以及存放在服務器上的遠程型。你可以用它來記錄用戶的相關信息(如用戶名、性別和其它設置參數等),或者用在服務器端,存儲其它聯機用戶實時分享的信息(如聊天室的內容和線上用戶名單等)
共享對象意味著用戶可以在不同的用戶之間、不同的同一臺服務器上的應用程序實體。FlashCom server 支持三種不同的共享對象:Local、remote和server-side。下面簡單介紹下這三個共享對象。
本地共享對象(Local shared object)
用于存取本地的數據,存儲在用戶的計算機硬盤中,并可以在不同的時間被其它應用程序訪問。本地共享對象的擴展名為.sol,默認的存儲路徑是c:\documents and Settings\登錄名稱\Application Data\Macromedia\Flash Player\服務器網域名稱\影片路徑\影片文件名.swf\。本地共享對象也可以是短暫的,也就是說只有但應用程序運行時可用。我們也可以不連接Flashcomserver而使用本地共享對象。更多的本地共享對象的信息,可以參考手冊中的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 apersistent
??? // shared object called myProxy they willreceive myProxy
??? // shared object from themaster_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 命令給所有連接到該遠程共享對象的客戶端廣播消息,也包括發送者本人。
FLASH COM學習筆記.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文件中定義我們需要的事件和方法。
FLASH COM學習筆記.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 :
如果在不同的網域訪問,就會彈出窗口讓用戶確認使用或是拒絕使用:
450) {this.resized=true; this.width=450;}" border=0>
當用戶對彈出窗口響應后就會觸發onStatus事件,請參考muted參數
當然也可以記住用戶的選擇,點擊鼠標右鍵出現設置窗口
450) {this.resized=true; this.width=450;}" border=0>
在該窗口選擇允許,并選中記住,下次就不會彈出確認窗口了。
更高級的示例是彈出設備選擇窗口讓用戶選擇:
1 : camArray = Camera.names;
2 : if (camArray.length == 1){
3 : Camera.get();
4 : }
5 : else
6 : System.showSettings(3);//彈出視頻設置窗口
7 : Camera.get();
?
450) {this.resized=true; this.width=450;}" border=0>
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 theStage
2 : c = Camera.get();
3 : myVideoObject.attachVideo(c);
4 : c.setMotionLevel(10, 500);
5 : c.onActivity = function (mode)
6 : {
7 : trace(mode);
8 : };
?
FLASH COM學習筆記.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);
?
FLASH COM學習筆記.11 NetConnection對象
?
對象簡介
如果要把本地端的視頻或者聲音傳遞給其它的客戶端,Flash影片就必須要聯機到FlashCom 服務器。聯機的方法就是通過NetConnect對象的connect()方法,連接到指定路徑的FlashCom應用程序。
FlashCom使用RTMP協議來共享和傳輸你的數據、聲音和視頻。
對象屬性:
isConnected 是否連接
uri 連接的URL地址,可以使用下面的方式
&S226; rtmp://www.myCompany.com/myMainDirectory/groupChatApp/HelpDesk
&S226; rtmpt:/sharedWhiteboardApp/June2002
&S226; 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 : }
?
FLASH COM學習筆記.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);//僅僅停止視頻播放,仍然保持音頻播放
更多的請期待FlashCom組件代碼分析專題。
?
FLASH COM學習筆記.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);
?
FLASH COM學習筆記.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 : }
?
FLASH COM學習筆記.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' );
?
FLASH COM學習筆記.16 SharedObject對象
?
我似乎反復的在講共享對象了,實在是我覺得共享對象在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
//取得當前(本地或遠程)共享對象的字節大小
//var soSize= this.so.getSize();
SharedObject.send
//對所有聯機用戶廣播消息
01 : // Create a remote shared object called remoteSO
02 : // Place an Input Text text box named inputMsgTxt on the Stage
03 : // Attach this code to a button labeled 'Send Message'
04 : on (release) {
05 : _root.remoteSO.send( 'testMsg' ,inputMsgTxt);
06 : }
07 : // Attach this code to the frame containing the button
08 : _root.remoteSO.testMsg = function(recvStr)
09 : {
10 : trace(recvStr);
11 : }
12 : // Type data in the text box and press the button to see the results
SharedObject.setFps
//設定客戶端更新的速率
共享對象的創建方法
SharedObject.getLocal(對象名稱);//不需要服務器端支持,只用于本地存儲
01 : // Get the kookie
02 : so = sharedobject.getlocal( 'kookie' );
03 : // Get the user of the kookie and go to the frame number saved for thisuser.
04 : if (so.data.user != undefined) {
05 : this.user = so.data.user;
06 : this.gotoAndStop(so.data.frame);
07 : }
08 : The following code block is placed on each movie frame.
09 : // On each frame, call the rememberme function to save the frame number.
10 : function rememberme() {
11 : so.data.frame=this._currentFrame;
12 : so.data.user= 'John' ;
13 : }
SharedObject.getRemote(對象名稱,聯機網址);//建立暫存的遠程共享對象,重啟即失效
1 : conn = new NetConnection();
2 : conn.connect( 'rtmp://somedomain.com/applicationName' );
3 : myObject = SharedObject.getRemote( 'mo' , conn.uri, false);
4 : myObject.connect(conn);
SharedObject.getRemote(對象名稱,聯機網址,true);//遠程共享對象數據存入服務器,在服務器端會保存'對象名稱.fso'文件
共享對象的屬性
data屬性(不再詳述)
共享對象的方法
共享對象的事件
SharedObject.onStatus //共享對象返回錯誤、警告或狀態的事件
SharedObject.onSync //同步事件
下面的實例可以參考:
01 : function getMaster()
02 : {
03 : trace( 'getMaster called' );
04 : master = SharedObject.getRemote( 'master' , con.uri, true);
05 : connVal = master.connect(con);
06 : if (connVal) print ( 'Connection was successful' );
07 : else print( 'Unable to connect the shared object with the givenNetConnection object' );
08 : master.onSync = function (listVal) {
09 : getPlayList();
10 : trace( 'SO: ' + so.data[currentPlaylist]);
11 : }
12 : }
?
FLASH COM學習筆記.17 應用程序設計和開發
?
這篇內容主要講述在FCS應用程序開發過程的一些建議和技巧,包含有服務器兼容性方面的建議、相互依賴關系、多文件管理、帶寬管理、雙字節支持、卸載和重載應用程序和動態訪問控制等~
一、服務器兼容性方面的建議
使用小寫方式命名你的目錄和文件名
Macromedia 推薦你使用小寫字母命名FlashCom開發項目中的目錄和文件,以便更好的工作在不同的服務器之間。
使用相對路徑或絕對路徑連接服務器
在Fcs開發中NetConnect.connect命令可以使用絕對和相對路徑來連接指定的應用程序,如果你的swf文件和FlashCom服務器運行在同一臺機器,你可以使用相對路徑rtmp:/appName/instanceName來代替
rtmp://server.domain.com/appName/instanceName
如果你的開發你的應用程序在一臺開發服務器,并且沒有使用相對路徑在swf文件中,那么移動你的swf文件到產品服務器會帶來一些額外的工作,因為你不得不更改每一個NetConnect.connect語句中url參數。
如果你的swf文件不會和flashCom服務器在同一臺機器,那么必須加上絕對路徑,(作者注:當然可以通過變量的方法來設置)
二、相互依賴關系
因為客戶端和服務器端的ActionScript腳本代碼都是應用程序的一部分,他們必須協調工作,并且相互依賴。一個最典型的例子就是在客戶端和服務器端之間使用call命令,因為調用的方法可能是客戶端或者服務器端自定義的。下面有個例子可以說明:
01 : // 客戶端fla文件的 ActionScript 代碼
02 : my_nc = new NetConnection();
03 : my_nc.someClientMethod = function()
04 : {
05 : //在這里添加你的處理代碼
06 : }
07 : my_nc.connect(“rtmp://hostname:port/appname”);
08 :
09 : // 服務器端的main.asc中的 ActionScript 代碼
10 : clientObj.call('someClientMethod');
在服務器端clientObj.call方法傳遞的參數必須是在客戶端已經定義好的NetConnect對象方法,這是因為任何客戶端的需要被服務器調用的方法必須通過NetConnect對象連接到服務器才可以。
相反,你在客戶端調用服務器端的方法
01 : // 客戶端代碼
02 : NetConnection.call( 'someServerMethod' );
03 :
04 : // 服務器端代碼
05 : client.prototype.someServerMethod = function()
06 : {
07 : // 這里是處理代碼
08 : }
09 : // 或者使用下面的調用方式也是有效的
10 : onConnect(newClient)
11 : {
12 : newClient.someServerMethod = function()
13 : {
14 : // code
15 : }
16 : }
在這種情況下,NetConnect.connect方法的參數必須是服務器端(一般是main.asc)已經定義好的方法,這是因為任何服務器端需要被客戶端調用的方法必須是服務器端的Client對象的方法。
三、使用多文件管理
當你的應用程序日益復雜的時候,不要企圖通過一個單一的腳本來完成所有的事情。把你的函數分成不同的文件,每個提供一定的功能集合。如果你使用多個文件,還可以使用包含的方式來優化性能,使得同一段代碼不需要被執行多次。
客戶端
例如,在客戶端,如果你想把my_file.as文件能夠被應用程序中的其它文件調用,只需要在my_file.as文件開頭寫上下面的代碼:
1 : if (_root._my_file_as == null) {
2 : _root._my_file_as = true;
3 : // All the code for myfile.as goes here
4 : }
然后,在其它文件中,包含下面代碼:
#include 'my_file.as';
注意:include指令在編譯時候被執行,而不是運行的時候執行。
服務器端
服務器端的方式有些區別,因為在服務器端的ActionScript不支持全局對象。例如,你要包含一個my_flie.asc文件,在該文件開頭依然包含下面這段代碼:
1 : if (_my_file_asc == null) {
2 : _my_file_asc = true;
3 : // All the code for myfile.asc goes here
4 : }
區別就在于其它文件包含該文件的時候不使用#i nclude指令,而是使用load指令
load('my_file.asc');
四、使用唯一的實體命名
通常的開發環境是多個用戶同時連接到同一臺服務器,為了避免數據流沖突或共享對象被覆蓋,可以在NetConnect.connect命令中使用唯一的實體名稱。
如果你想要使用NetConnect 調試工具,你必須在客戶端代碼的第一行包含NetDebug.as文件,(FlashCom1.5版本并沒有包含NetDebug.as文件,你可以在這里下載)NetDebug.as文件的使用方法不在本文的說明范疇,留待以后再表。
五、強制顯示Flash設置面板
當一個應用程序企圖訪問用戶的攝像機或者麥克風,以及要在本地存儲數據的時候,flash 會顯示設置對話框來得到允許。用戶也可以點擊鼠標右鍵來打開設置面板。如果要強制顯示設置面板,可以使用下面的代碼:
// 不帶參數表示打開用戶上次瀏覽的設置面板
1 : System.ShowSettings();
2 : // 打開保密性設置面板
3 : System.ShowSettings(0);
4 : // 打開本地存儲設置面板
5 : System.ShowSettings(1);
6 : // 打開麥克風設置面板
7 : System.ShowSettings(2);
8 : // 打開照相機設置面板
9 : System.ShowSettings(3);
例如,如果你的應用程序需要使用攝像頭,你可能需要提示用戶在彈出的保密性設置面板中選擇允許。就必須使用
System.showSettings(0)
六、帶寬管理
你可以通過計算近似的帶寬承受度來控制服務器發送到每個客戶端的數據量。有很多種方法可以做到,一種方法是配置FlashCom server的config.xml文件;另一種方法是使用NetStream.receiveVideo 方法來指定傳輸速率;第三種方法是通過設置客戶端Camera.Quality屬性和服務器端的Client.setBandwidthLimit方法。下面會詳細講述第三種方法。
Fcs自帶的doc_bandwidth示例程序演示如何讓用戶選擇不同的帶寬設置。選擇不同的帶寬設置后,客戶端的麥克風和攝像頭設置也會根據用戶的選擇更新,服務器端的帶寬限制也會更新。
客戶端的ActionScript提供了一個用戶界面讓用戶選擇三種不同的帶寬設置:Modem、DSL和LAN。當用戶改變了帶寬限制后,攝像頭和麥克風設置也會更新,還有一個不引人注意的地方,就是updateBandwidth方法也會根據設置的選擇改變屏幕的尺寸。
01 : _root.Modem_btn.onPress = function() {
02 : // Call updateBandwidth to change
03 : // camera and mic settings and inform
04 : // the server
05 : _root.updateBandwidth(1);
06 : }
07 : _root.DSL_btn.onPress = function() {
08 : _root.updateBandwidth(2);
09 : }
10 : _root.LAN_btn.onPress = function() {
11 : _root.updateBandwidth(3);
12 : }
在fla文件的第一幀,你可以找到下面一段代碼,用來初始化攝像頭和麥克風,以及從服務器播放串流和根據用戶的選擇更新攝像頭、麥克風的設置。
01 : #i nclude 'NetDebug.as'
02 : stop();
03 : // Initialize movie by getting a camera and microphone, and
04 : // Configure the initial camera and microphone settings
05 : client_cam = Camera.get();
06 : client_cam.setMode(150,120,5);
07 : client_cam.setQuality(0, 90);
08 : client_mic = Microphone.get();
09 : client_mic.setRate(22);
10 : // Get the stream to publish and play
11 : function getPlayStream() {
12 : // Get new net connection
13 : client_nc = new NetConnection();
14 : // Handle status message
15 : client_nc.onStatus = function(info) {
16 : trace( 'Level: ' + info.level + newline + 'Code: ' + info.code);
17 : }
18 : client_nc.connect('rtmp:/doc_bandwidth/room_01');
19 : // Create a stream to which to publish
20 : out_ns = new NetStream(client_nc);
21 : out_ns.attachVideo(client_cam);
22 : out_ns.attachAudio(client_mic);
23 : out_ns.publish('myAV');
24 : Chapter 5 70
25 : // Create a stream to receive the published data
26 : in_ns = new NetStream(client_nc);
27 : Output_mc.fromSrvr.attachVideo(in_ns);
28 : Output_mc.fromSrvr.attachAudio(in_ns);
29 : in_ns.play('myAV');
30 : }
31 : // Called from the bandwidth buttons
32 : function updateBandwidth(b) {
33 : // Respond to a change in the bandwidth
34 : // If 'Modem' was selected
35 : if ( b == 1 ) {
36 : client_cam.setMode(160,120,2);
37 : client_cam.setQuality(0, 75);
38 : client_cam.setKeyFrameInterval(3);
39 : client_mic.setRate(5);
40 : // For demonstration purposes, change size of screen
41 : Output_mc._height = 100;
42 : Output_mc._width = 150;
43 : // If 'DSL' was selected
44 : } else if ( b == 2 ) {
45 : client_cam.setMode(160,120,5);
46 : client_cam.setQuality(0, 85);
47 : cam.setKeyFrameInterval(5);
48 : client_mic.setRate(11);
49 : // For demonstration purposes, change size of screen
50 : Output_mc._height = 130;
51 : Output_mc._width = 175;
52 : // If 'LAN' was selected
53 : } else {
54 : client_cam = Camera.get();
55 : client_cam.setMode(160,120,15);
56 : client_cam.setQuality(0, 90);
57 : client_cam.setKeyFrameInterval(10);
58 : client_mic.setRate(22);
59 : // For demonstration purposes, change size of screen
60 : Output_mc._height = 150;
61 : Output_mc._width = 200;
62 : }
63 : // Call the server function setBandwidth and pass the user’s
64 : // selection, b.
65 : client_nc.call('setBandwidth', 0, b);
66 : }
67 : // Get the stream to play
68 : getPlayStream();
在服務端的main.asc文件中,包含了setBandwidth方法,被客戶端調用。
01 : // If server-side code is part of the application,
02 : // it must define an onConnect function that accepts
03 : // the client connection.
04 : application.onConnect = function(client) {
05 : // Establish the connection
06 : application.acceptConnection(client);
07 : }
08 : // Called when user presses a bandwidth choice (Modem=1, DSL=2, LAN=3)
09 : Client.prototype.setBandwidth = function(bw) {
10 : // set the bandwidth for the client
11 : if ( bw == 1 ) {
12 : // modem settings
13 : this.setBandwidthLimit( 35000/8, 22000/8 );
14 : } else if ( bw == 2 ) {
15 : // DSL settings
16 : this.setBandwidthLimit( 800000/8, 100000/8 );
17 : } else {
18 : // LAN settings
19 : this.setBandwidthLimit( 400000, 400000 );
20 : }
21 : }
七、開發雙字節應用程序
如果需要在服務器端的開發環境使用雙字節文字,你的服務器端ActionScript代碼必須使用utf-8編碼。這意味著你必須采用支持UTF-8的編輯器書寫代碼,然后可以用內建的JavaScript方法,例如Date.toLocalString 來轉換成本地編碼。
如果使用雙字節字符作為方法名稱,必須使用對象數組操作方式而不能用點操作方式。
1 : // 使用雙字節命名的方法格式
2 : obj['方法名稱'] = function(){ }
3 : // 使用單字節命名的方法格式
4 : obj.MethodName = function() { }
八、卸載和重載應用程序
應用程序實體會自動卸載通過垃圾回收機制。當所有的用戶斷開應用程序的連接的時候,垃圾回收會首先運行,然后應用程序會自動卸載。換句話說,并不是所有用戶斷開連接的時候應用程序就馬上卸載。因為應用程序的啟動通常需要一段時間,所以下一個客戶端的連接并不會占用啟動的開銷。
默認,垃圾回收每20分鐘發生一次,你可以修改這個值(必須大于0)。
當你對main.asc文件有任何修改的時候,你必須重載應用程序才可以生效。而這樣就會斷開當前所有用戶的連接。重載應用程序的方法可以通過管理控制臺和應用程序監視器來完成。
九、執行動態訪問控制
服務器端的ActionScript給共享對象和串流對象提供了執行動態訪問控制列表(ACL)的功能機制。默認所有的連接對串流和共享對象有完全訪問權限。你可以控制某個用戶具有創建、讀寫共享對象和串流的權限,每個連接到服務器端的應用程序實體都會有一個服務器端的Client對象參考,并且每一個Client對象都有兩個屬性:readAccess和writeAccess。使用這兩個屬性,就可以設置每個連接的權限。
下面有個示例:
client.readAccess = 'appSO/'
client.writeAccess = 'appStreams/public/;appSO/public/'
該例子說明了對一個Client對象實體client作了權限控制
如果要對全部Client對象設置權限,可以使用
client.readAccess = 'appSO/' ; //所有客戶端都可以訪問appSO目錄
client.writeAccess= 'appSO/public/'; //所有連接的客戶端都可以該目錄下創建共享對象或數據流
但是卻無法寫入 appSO/private/ 目錄。
?
FLASH COM學習筆記.18 良好的編程習慣
?
本節內容概述了在使用actionscript編程和創建應用程序的時候需要遵循的一些規則,以及如何使我們的程序代碼更有效和具有更好的可讀性,更方便調試應用程序。
把這節寫在前面,也是為了讓開始接觸ActionScript編程的開發人員從一開始就養成好的編程和開發習慣。
1. 遵循命名規則
一個應用程序的命名規劃必須保持一致性和可讀性。任何一個實體的主要功能或用途必須能夠根據命名明顯的看出來。因為ActionScript是一個動態類型的語言,命名最好是包含有代表對象類型的后綴。一般而言,名詞_動詞和形容詞_名詞之類的語法是最常用的命名方式,如:
影片名字:my_movie.swf
URL實體:course_list_output
組件或對象名稱:chat_mc
變量或屬性:userName
方法和變量的名稱應該以小寫字母開頭,對象和對象的構造方法應該大寫。命名變量的時候使用大小寫混和的方式,并且使用字母打頭,還可以包含數字和下劃線。
下面的一些命名是非法的:
_count =5 ;//首字符不能使用下劃線
5count = 0;//首字符不能使用數字
foo/bar = true;//包含非法字符
另外,ActionScript使用的保留字不能用來命名變量。
ActionScript是基于ECMAScript,所以我們可以根據ECMAScript的規范來命名。如,
course_list_output = 'foo'; //全部小寫,使用下劃線分割字串
courseListOutput = 'foo'; // 大小寫混和的方式
BASEURL = http://www.foo.com; // 常量使用全部大寫
MAXCOUNTLIMIT = 10;
MyObject = function(){ }; // 構造函數
f = new MyObject(); // 對象
注意;良好的命名規范還可以使用Flash的代碼提示功能。
2. 給你的代碼添加注釋
? 使用代碼注釋能夠使得程序更清晰,也便于我們閱讀。Flash支持的代碼注釋方法有兩種:
?單行注釋,通常用于變量的說明
var clicks = 0; // variable for number of button clicks
?多行注釋,通常用于功能說明和大段文字的注釋:
/*
Initialize the clicks variable that keeps track of the number of times
the button has been clicked.
*/
一些具有特定意思的注釋方法:
// :TODO: topic
表明一個主題的開始
// :BUG: [bugid] topic
顯示了一個BUG所在
// :KLUDGE:
表明下面的代碼并不完善,可能存在問題
// :TRICKY:
告訴開發人員下面的代碼具有相互作用,修改之前請謹慎
3. 保持代碼的整體性
無論什么情況,應該盡可能保證所有代碼在同一個位置,這樣使得代碼更容易搜索和調試。我們在調試程序的時候很大的困難就是定位代碼,如果大部分代碼都集中在同一幀,問題就比較好解決了。通常,我們把代碼都放在第一幀中,并且單獨放在最頂層。如果在第一幀中集中了大量的代碼,記得用注釋標記區分,并在開頭加上代碼說明。
1 : //===========================================
2 : // 視頻語音聊天系統
3 : // FCAVPresence組件
4 : // Copyright ◎2002 Macromedia, Inc. All rights reserved.
5 : // 完善:Liu21st, Liu21st@126.com
6 : //---------------------------------------------------------
在獨立的功能模塊前面加上類似的標注:
1 : //===========================================
2 : // 參數初始化
3 : //---------------------------------------------------------
4. 初始化應用程序
記得一定要初始化你的應用程序,init函數應該是你的應用程序類的第一個函數,如果使用面向對象的編程方式則應該在構造函數中進線初始化工作。該函數只是對應用程序中的變量和對象初始化,其它的調用可以通過事件驅動。
下面的例子可以說明如何進線初始化
1 : function FCAVPresenceClass() {
2 : this.init();
3 : }
4 : FCAVPresenceClass.prototype.init = function() {
5 : this.name = (this._name == null ? '_DEFAULT_' : this._name);
6 : this.prefix = 'FCAVPresence.' + this.name + '.';
7 : };
5.使用局部變量
所有的局部變量使用關鍵字var來申明,這樣可以避免被全局變量訪問,更重要的是,可以保證變量不被覆蓋和混淆程序邏輯。例如,下面的代碼沒有使用var來申明,覆蓋了其它變量。
01 : counter = 7;
02 : function loopTest()
03 : {
04 : trace(counter);
05 : for(counter = 0; counter < 5; counter++)
06 : {
07 : trace(counter);
08 : }
09 : }
10 : trace(counter);
11 : loopTest();
12 : trace(counter);
輸出結果為:
7
7
0
1
2
3
4
5
6. 創建對象時使用原型添加方法和屬性
當我們創建一個對象的時候,應當使用原型方式來添加對象的方法或屬性,使得該方法或屬性能夠被所有該對象或子對象的實體所訪問。這種能夠確保內存中每個函數只有一份拷貝。作為一般的規則,不要在構造函數中定義方法。下面是一個正確的例子:
01 : // Best practice for creating an object
02 : MyObject = function()
03 : { }
04 : MyObject.prototype.name = '';
05 : MyObject.prototype.setName = function(name)
06 : {
07 : this.name = name;
08 : }
09 : MyObject.prototype.getName = function()
10 : {
11 : return this.name;
12 : }
下面這段代碼是不可取的:
01 : // Less desirable practice for creating an object
02 : MyObject = function()
03 : {
04 : this.name = '';
05 : this.setName = function(name)
06 : {
07 : this.name = name;
08 : }
09 : this.getName = function()
10 : {
11 : return this.name;
12 : }
13 : }
使用上面的方式在每個對象的實體被創建的時候都會實體重新復制每一個屬性和方法,會加重系統的內存開銷。
7. 規范命名方式獲取代碼提示功能
這方面我已經有過詳細的敘述,請看:
[ actionscript代碼提示功能 ]和 [ 面向對象方式的代碼提示功能 ]
?
FLASH COM學習筆記.19 服務器管理-Actionscript API
?
FlashCom Server MX 1.5 包含了服務器管理的ActionScript API,提供了一些高級的方法集用來擴展管理控制臺,讓我們可以自己開發Flash應用程序的管理和監視工具。
使用服務器管理ActionScript API
為了使用服務器管理ActionScript API,你必須安裝有FlashMX和FlashComserver,并且具有FlashCom Server的管理權限。當然,你還能很熟練的用ActionScript來編寫Flash應用程序。
掌握服務器管理ActionScript API最好的方法是查看管理控制臺的源代碼。注冊用戶可以在Macromedia的下載中心下載到admin.fla文件。
建立服務器連接
FlashCom Server的默認端口是1935,但是,為了使用服務器管理Actionscript API,你必須連接到管理端口,默認1111。連接服務器的方式和Flashcom應用程序一樣使用
NetConnect.connect方法,不同的是需要傳遞三個參數:服務器管理目錄的url,管理員用戶名,管理員密碼。有效的管理員名稱和密碼是在配置文件Server.xml中定義的。下面是連接示例:
1 : nc = new NetConnection();
2 : nc.connect('rtmp://localhost:1111/admin', 'admin', '1234');
為了使用更安全的用戶認證機制,建議使用防火墻控制對1111端口。[筆者注:更多的關于安全方面的內容以后會專門敘述]
語法示例
要使用服務器端ActionScript API 的方法,你必須使用call指令并使用相應的參數。
下面的示例中,getAppStats方法被調用,并由new receiveAppStats事件處理反饋信息,ChatApp是該方法需要傳遞的應用程序名參數。
1 : nc = new NetConnection();
2 : nc.connect('rtmp://localhost:1111/admin', 'MHill', '635xjh27');
3 : // Call getAppStats
4 : nc.call('getAppStats', new receiveAppStats(), 'ChatApp');
一個簡單的應用程序例子
下面的例子調用了getAppStats方法來查看服務器的應用程序chatApp的狀態
appName 是一個文本輸入框的實例名
outputBox 是返回結果的文本框實例名
01 : /** Establishes the connection to Flash Communication Server**/
02 : nc = new NetConnection();
03 : nc.connect('rtmp://localhost:1111/admin','admin_name','admin_pass');
04 : /** Makes the API call, for example, 'GetAppStats' **/
05 : function doGetAppStats() {
06 : function onGetAppStats()
07 : {
08 : this.onResult = function(info)
09 : {
10 : if (info.code != 'NetConnection.Call.Success')
11 : outputBox.text = 'Call failed: ' + info.description;
12 : else {
13 : outputBox.text = 'Info for '+appName.text+ ' returned:' + newline;
14 : printObj(info, outputBox);
15 : }
16 : }
17 : }
18 : nc.call('getAppStats', new onGetAppStats(), appName.text);
19 : }
20 : // This function proceeds through an object, printing all values to the
21 : // destination, including recursively printing objects within objects.
22 : // The tabLevel parameter is used for cosmetic purposes.
23 : function printObj(obj, destination, tabLevel)
24 : {
25 : if (arguments.length < 2) {
26 : trace('ERROR! you need to supply a text object to output to');
27 : return;
28 : }
29 : if (arguments.length < 3)
30 : tabLevel = 0;
31 : for (var prop in obj) {
32 : for (var i = 0; i < tabLevel; i++) // insert requested # of tabcharacters
33 : destination.text += '\t';
34 : destination.text += prop + ' = ' + obj[prop] + newline;
35 : if (typeof (obj[prop]) == 'object') { // recursively call printObj
36 : printObj(obj[prop], destination, tabLevel+1 );
37 : }
38 : }
39 : }
40 : // Alerts you if there are errors connecting to the server.nc.onStatus =
41 : function(info) {
42 : if (info.code == 'NetConnection.Connect.Success') {
43 : trace('Connected! The call should work')
44 : } else {
45 : // use nc.isConnected to test condition of server
46 : if (! nc.isConnected)
47 : trace('NO netConnection to server. Call will not work');
48 : }
49 : }
服務器端信息對象
所有服務器端ActionScript API 方法返回值都都保存在信息對象的相關屬性中,這些屬性和客戶端的信息對象屬性有所區別,分別是:level, code, timestamp, data, description和details。其中level, code和 timestamp 屬性是全部都具備的,其它屬性是某些方法才具有的。data屬性通常用來返回對象或數組數據,description和details屬性通常提供一些錯誤信息。
方法總結
服務器管理ActionScript API包含了三種類型的方法:
查詢方法:查看你的FlashCom服務器、應用程序和指定的應用程序實例的狀態信息;
管理方法:對Flashcom服務器的用戶管理、服務器管理和應用程序管理等
配置方法:查看和設置服務器的配置文件
有些方法只有管理員才有權限操作(用*號注明),虛擬主機的管理員不能夠使用這些方法。
查詢方法概要
01 : getActiveInstances 返回包含所有正在運行中的應用程序實例名的數組
02 : getAdaptors Returns an array of adaptor names.
03 : getAdminContext Returns the administrative context for the administrator(administrator type, name of
04 : adaptor, and name of the virtual host).
05 : getApps 返回所有應用程序的名稱數組
06 : getAppStats 返回指定應用程序的所有實例的集合信息
07 : getInstanceStats 返回當前運行的應用程序實例的詳細信息
08 : getIOStats 返回 I/O 信息 *
09 : getLicenseInfo 返回license 信息
10 : getLiveStreams 返回指定應用程序當前發布的所有實時串流信息
11 : getLiveStreamStats 返回串流的詳細信息
12 : getMsgCacheStats 返回服務器TCMessage緩存狀態信息.
13 : getNetStreams 返回當前連接到應用程序的所有的NetStream列表
14 : getNetStreamStats 返回指定NetStream的詳細信息.
15 : getScriptStats 得到指定應用程序實例的腳本運行信息
16 : getServerStats 取得服務器狀態和統計信息*
17 : getSharedObjects 返回當前應用程序實例的所有共享對象數組
18 : getSharedObjectStats 返回共享對象的詳細信息
19 : getUsers 返回連接當前到應用程序實例的所有用戶數組
20 : getUserStats 返回指定用戶的詳細信息
21 : getVHosts 返回虛擬主機的數組
22 : getVHostStats 返回虛擬主機的統計信息
23 : ping 返回服務器狀態標記的信息
管理方法概要
01 : addAdmin 添加一個系統管理員*
02 : addApp 添加一個新的應用程序(會自動創建目錄)
03 : changePswd 更改管理員密碼
04 : gc 強制服務器端的資源垃圾回收*
05 : reloadApp 重啟應用程序,會先卸載該應用程序的實例
06 : removeAdmin 刪除管理員*
07 : removeApp 刪除應用程序或應用程序實例
08 : restartVHost 重啟虛擬主機
09 : startServer 啟動FlashCom Server*
10 : startVHost 啟動指定的虛擬主機*
11 : stopServer 停止FlashCom Server*
12 : stopVHost 停止虛擬主機
13 : unloadApp 卸載應用程序以及所有實例,端口用戶連接
配置方法概要
1 : getConfig 返回指定配置鍵的配置信息
2 : setConfig 設置指定的配置鍵
關于每個方法的詳細資料請參考手冊中的說明。
?
FLASH COM學習筆記.20 拍攝和創建影片場景
?
這一節講述如何通過FlashCom Server來實現拍攝和創建影像索引功能,這個技術對于需要保存影像數據非常有用。
拍攝功能
我們在NetStream.attachVideo 的方法中已經提到過
myStream.attachVideo(source | null [ , snapShotMilliseconds ])
snapShotMilliseconds參數就是用來設置抓屏的時間間隔,如果設置成0,表示只抓取一個單元格畫面,如果大于0的話,就表示以該秒數為時間間隔,連續拍攝單元格影像。
下面我們來看下FlashCom自帶的一個范例 doc_snapshot.fla的拍攝功能的實現。
01 : #i nclude 'NetDebug.as'
02 : // Recording state variable
03 : RecState_box.text = 0;
04 : // Number of snapshots
05 : numSnaps = 0;
06 : // Initialize button label
07 : Record_btn.setLabel('Record');
08 : // Connect to the snapshot app and get connection status
09 : function doConnect() {
10 : client_nc = new NetConnection();
11 : client_nc.onStatus = function(info) {
12 : trace('Level: ' + info.level + newline + 'Code: ' + info.code);
13 : };
14 : client_nc.connect('rtmp:/doc_snapshot/room_01');
15 : }
16 : // Create a stream for recording and getting the snapshot
17 : function initStreams() {
18 : // Stream for recording
19 : out_ns = new NetStream(client_nc);
20 : out_ns.onStatus = function(info) {
21 : trace('Level: ' + info.level + newline + 'Code: ' + info.code);
22 : };
23 : // Stream for playing
24 : in_ns = new NetStream(client_nc);
25 : in_ns.onStatus = function(info) {
26 : trace('Level: ' + info.level + newline + 'Code: ' + info.code);
27 : };
28 : }
29 : // Get a camera instance and attach it to the local
30 : // video, Live_video, and the output stream
31 : client_cam = Camera.get();
32 : Live_video.attachVideo(client_cam);
33 : // Button event handler for publishing and showing the snapshot
34 : function doRecord() {
35 : // If you’re not recording, begin to record
36 : if (RecState_box.text == 0) {
37 : // Clear the snapshot window
38 : Snapshot_mc.removeMovieClip();
39 : // 關鍵的實現代碼
40 : //拍攝一個單元格畫面
41 : out_ns.attachVideo(client_cam, 0);
42 : out_ns.publish('myRecording'+numSnaps, 'record');
43 : // Set the label to stop
44 : Record_btn.setLabel('Stop');
45 : // Update the recording state
46 : RecState_box.text = 1;
47 : // If you’re recording, stop
48 : } else {
49 : // Stop publishing recorded stream
50 : out_ns.publish(false);
51 : // Close the stream so that we can use the same to publish again
52 : out_ns.close();
53 : // Set the label to 'Record'
54 : Record_btn.setLabel('Record');
55 : // Update the recording state
56 : RecState_box.text = 0;
57 : showSnapshot();
58 : }
59 : }
60 : // Show the snapshot by attaching the stream to the SnapView_video
61 : // video object and playing it
62 : function showSnapshot() {
63 : // Create a new movie clip from the exportable movie clip View_mc,
64 : // which contains a video object, SnapView_video. Provide a new name, and
65 : // depth (a number relative to the other View_mcs on the stage used
66 : // to prevent collision)
67 : _root.attachMovie('View_mc', 'Snapshot_mc', numSnaps);
68 : // Attach the input stream to the SnapView_video video object
69 : // in the v instance of the View_mc movie
70 : Snapshot_mc.SnapView_video.attachVideo(in_ns);
71 : Snapshot_mc._x=375;
72 : Snapshot_mc._y=225;
73 : // Play the recording
74 : in_ns.play('myRecording'+numSnaps);
75 : // Update the counter for the number of snapshots for next time.
76 : numSnaps++;
77 : }
78 : // Connect to the server
79 : doConnect();
80 : // Initialize the streams
81 : initStreams();
創建影像索引
影像索引是創建原始的影像的縮略查看,類似于拍攝功能,都提供了單幀的影像數據,區別在于拍攝功能是獲取一幀影像,而影像索引一般是播放錄制影像的第一幀。
在前面的例子中,我們通過設置snapShotMilliseconds參數來得到影像的拍攝,在下面的例子中,我們還需要使用NetStream.play方法來實現播放單一幀:
thumbStream.play('myRecording', 0, 0, true)
中間兩個參數表示播放的開始和結束位置(0,0 表示從頭開始播放一幀),最后一個參數表示是否中斷之前的播放。
下面我們來參考下FlashCom的范例doc_thumbnails.fla 的實現方式。
01 : #i nclude 'NetDebug.as'
02 : // Recording state variable
03 : recState = 0;
04 : // Initialize button label
05 : Record_btn.setLabel('Record');
06 : // Show the recording in a thumbnail
07 : showThumb();
08 : // Connect to the thumbnails app and get connection status
09 : function doConnect()
10 : {
11 : client_nc = new NetConnection();
12 : // If connection is closed, clear the History and the list
13 : // Handle status message
14 : client_nc.onStatus = function(info) {
15 : trace('Level: ' + info.level + newline + 'Code: ' + info.code);
16 : }
17 : client_nc.connect('rtmp:/doc_thumbnails/room_01');
18 : }
19 : // Create a stream for recording and getting the thumbnail
20 : function initStreams()
21 : {
22 : out_ns = new NetStream(client_nc);
23 : out_ns.onStatus = function(info)
24 : {
25 : if (info.code == 'NetStream.Publish.Success') {
26 : var description = 'You have published.';
27 : trace(description);
28 : }
29 : };
30 : thumb_ns = new NetStream(client_nc);
31 : }
32 : // Get a camera instance and attach it to the local
33 : // video, Live_video, and the output stream
34 : function initMovie()
35 : {
36 : client_cam = Camera.get();
37 : Live_video.attachVideo(client_cam);
38 : out_ns.attachVideo(client_cam);
39 : }
40 : // Button event handler for publishing and showing the thumbnail
41 : function doRecord()
42 : {
43 : if (recState == 0) {
44 : out_ns.publish('myRecording', 'record');
45 : Record_btn.setLabel('Stop');
46 : recState = 1;
47 : } else {
48 : out_ns.publish(false);
49 : Record_btn.setLabel('Record');
50 : recState = 0;
51 : showThumb();
52 : }
53 : }
54 : // Show the thumbnail by attaching the stream to the ThumbView_vc
55 : // video object and playing it
56 : function showThumb()
57 : {
58 : ThumbView_vc.attachVideo(thumb_ns);
59 : thumb_ns.play('myRecording', 0, 0, true);
60 : }
61 : // Connect to the server
62 : doConnect();
63 : // Initialize the streams
64 : initStreams();
65 : // Initialize the movie
66 : initMovie();
?
FLASH COM學習筆記.21 Client對象
?
Client對象包含了每個聯機用戶的信息,例如:客戶端的IP地址、Flash和操作系統的信息、分配用戶的頻寬以及呼叫客戶端的函數。該對象必須在服務器端使用。
Clinet對象經常用來呼叫客戶端定義的方法,使用Client.call方法
例如我們在客戶端定義了一個獲取隨機數的方法
1 : nc = new NetConnection();
2 : nc.connect ('rtmp://someserver/someApp/someInst');
3 : nc.random = function(){
4 : return (Math.random());
5 : };
需要在服務器端使用該方法時,就可以通過client對象的call方法
01 : application.onConnect = function(clientObj){
02 : trace('we are connected');
03 : application.acceptConnection(clientObj);
04 : clientObj.call('random', new randHandler());
05 : };
06 : randHandler = function(){
07 : this.onResult = function(res){
08 : trace('random num: ' + res);
09 : }
10 : this.onStatus = function(info){
11 : trace('failed and got:' + info.code);
12 : }
13 : };
第二個參數是返回對象,如果有參數需要傳遞,依次跟在后面就可以了。
Client對象可以方便地獲取某個客戶端的相關信息,包括:
Client.agent 客戶端的平臺和版本信息
Client.ip 客戶端的 IP 地址
Client.protocol 客戶端連接到服務器的協議
Client.readAccess 客戶端具有讀操作的權限列表
Client.referrer 客戶端swf文件的URL地址
Client.writeAccess 客戶端具有寫操作的權限列表
使用方法如下:
1 : application.onConnect = function(client){
2 : if (client.ip == '127.0.0.1'){
3 : // insert code here
4 : } else {
5 : // insert code here
6 : }
7 : };
請注意不要和application.clients屬性相混淆,application.clients是所有聯機用戶的列表
application.clients[ i ]表示某個Client對象的實例
我們可以這樣訪問客戶端對象的屬性,
1 : for (var i = 0; i < application.clients.length; i++) {
2 : trace(application.clients[ i ].ip);
3 : }
關于限制帶寬的兩個方法
Client.getBandwidthLimit 取得帶寬限制值,分別取得客戶端到服務器端以及服務器端到客戶端的帶寬限制,如:
1 : application.onConnect = function(newClient){
2 : var clientToServer= newClient.getBandwidthLimit(0);
3 : var serverToClient= newClient.getBandwidthLimit(1);
4 : };
Client.setBandwidthLimit(iServerToClient,iClientToServer) 設置帶寬限制值
如果某個參數設為0,表示不改變當前的設置值。
查詢客戶端是否和服務器保持連通狀態可以使用Client.ping方法,如
1 : application.onConnect( newClient ) {
2 : if ( newClient.ping() ){
3 : trace('ping successful');
4 : }
5 : else {
6 : trace('ping failed');
7 : }
8 : }
注意有時候ping方法的響應時間比較久,要最有效的偵測客戶端是否和服務器端保持連通的方法是client和server端作相向回覆。
如果所有的客戶端對象的實例都需要使用相同的屬性和方法的時候,你可以把該屬性和方法擴展到類中,而不需要在客戶端為每一個實例創建方法。這樣可以減少客戶端的內存占用。這個過程稱為類的擴展,你可以擴展任何客戶端或服務器端的類。
擴展的方法或屬性不需要在類的架構函數中聲明(在架構函數中聲明的方法和屬性在每個實例初始化的時候都會分配一次),通過prototype屬性來擴展的方法和屬性在所有類的實體中都可以使用。
下面我們來看個例子,
1 : application.onConnect = function(clientObj){
2 : clientObj.birthday = myBDay;
3 : clientObj.calculateDaysUntilBirthday = function(){
4 : // insert code here
5 : }
6 : };
如果你希望一些方法和屬性能夠被所有application.clients數組中的客戶端使用,而不需要每次都定義。我們就可以通過對Client對象擴展,我們首先定義好需要的方法
1 : function Client_getWritePermission(){
2 : return this.writeAccess;
3 : }
4 : function Client_createUniqueID(){
5 : var ipStr = this.ip;
6 : var uniqueID = 're123mn'
7 : return uniqueID;
8 : }
然后給Client對象的prototype屬性添加我們定義的方法
1 : Client.prototype.getWritePermission =Client_getWritePermission;
2 : Client.prototype.createUniqueID = Client_createUniqueID;
3 :
你也可以添加屬性給Clent對象,如
Client.prototype.company = 'Macromedia';
這些方法和屬性對于任何一個Client對象的實例都時可用的。
1 : application.onConnect = function(clientObj){
2 : var clientID = clientObj.createUniqueID();
3 : var clientWritePerm = clientObj.getWritePermission();
4 : };
?
FLASH COM學習筆記.22 Flash Com Framework
?
FlashCom的Framework寫的很不錯,對深入研究actionscript和flashcom都有一定幫助。
把function的幾篇相關文章摘讀一下
原文出處:http://blog.funciton.com/en/archives/000254.php
本人對原文做了部分刪減,增加了一些原文沒有的代碼參考。
第一部分
MM的FlashCom Server Framework原本是和組件相關聯的,但是其中添加了不少有用的功能,我們依然可以在不使用FlashCom組件的情況下來使用該Framework(Function組件就是一個例子)。
一個FlashCom Server只能運行一個application對象以及相關事件,比如說,我們只能在main.asc文件中定義一個application.onAppStart,application.onConnect等,但問題是,我們如何管理每個組件類的私有應用程序事件。
下面我們來一步一步揭開Framework的神秘面紗。
Framework怎樣對應用程序對象建立廣播(類似于FlashMX2004中的EventDispatcher 類和Flash MX中的AsBroadcaster對象)?
它的方式是否就像是一個應用程序事件通過廣播調用和調用所有的對象事件?
那么這些組件放置在gFrameworkFC對象的什么地方?
注:gFrameworkFC對象是由Framwork建立的一個全局對象
每一個組件實例都基于gFrameworkFC對象中的components對象,如果有更多的對象被建立會是什么情況?
它們通過基于服務器端類的命名空間放置在不同的位置,并且可以實例化。
例如:FCChat組件類的命名空間是
gFramework.components.FCChat.clientSideComponentInstance
如果我們有多個chat組件,FCChat對象需要兩個屬性來指向不同的組件實例。
我們沒有涉及到客戶端的組件實例,事實上我們僅僅需要操作服務器端對象而無需直接操作客戶端對象。
Framework具有下面些常用的對象
gFrameworkFC 全局對象
clientGlobals 客戶端全局對象
components 組件對象
第二部分
我們都知道服務器端的參數不能傳遞一個真正的數組,我們需要把數據連接起來,這給我們傳值帶來很大的不便。
事實上FlashCom的工程師通過Framework解決了這個問題,他們嘗試過很多種方法,直到FlashCom1.5 updater1出來后,這個問題才真正的解決。通過gFrameworkFC全局對象的__toarray__方法,究竟如何使用呢,我們先來看下該方法的定義。
1 : gFrameworkFC.__toarray__ = function(obj) {
2 : if ( typeof(obj) != 'object' || obj.constructor == Array || obj[ 'length' ]== null )
3 : return obj;
4 : var a = new Array(obj.length)
5 : for ( var i = 0; i < obj.length; i++ )
6 : a[ i ] = obj[ i ];
7 : return a;
8 : }
使用的時候我們只需要通過調用對象的arguments參數,通過__toarray__方法返回一個真正的數組對象。如:
1 : application.onConnect = function (){
2 : // arguments is not a real array
3 : var t = gFrameworkFC.__toarray__( arguments );
4 : }
這樣,t就是一個數組,我們可以對它進行諸如concat, splice, pop, push之類的數組操作了。
另外一個很重要的地方是,每個連接的客戶端對象都將通過Framework賦予一個唯一的ID,當應用程序重新啟動的時候這個ID的值初始化為 0 ,這個ID被getClientGlobals和getClientLocals方法所調用,這在下個部分會詳細描述。
你可以通過__ID__ 屬性來訪問,如果你使用服務器端組件的話,也可以使用下面的方式訪問到
1 : //FCMySSComponent是服務器端的組件實例名
2 : var id = FCMySSComponent.getClientID(client);
其實很簡單但是非常有意思,你說呢?
第三部分
現在來講述getClientGlobalStorage和getClientLocalStorage方法。
在gFrameworkFC對象中并沒有直接定義getClientGlobalStorage和getClientLocalStorage方法,只是定義了getClientGlobals方法。
1 : gFrameworkFC.getClientGlobals = function(client) {
2 : return this.clientGlobals[client.__ID__];
3 : }
getClientGlobalStorage和getClientLocalStorage方法就是在components對象中定義的
01 : FCComponent.prototype.getClientGlobalStorage = function(client ) {
02 : return gFrameworkFC.getClientGlobals(client);
03 : }
04 : FCComponent.prototype.getClientLocalStorage = function( client ) {
05 : if ( this.clientLocalStorage == null )
06 : this.clientLocalStorage = new Object();
07 : var cls = this.clientLocalStorage[client.__ID__];
08 : if ( cls == null )
09 : cls = this.clientLocalStorage[client.__ID__] = new Object();
10 : return cls;
11 : }
這兩個方法非常有用,用來區分全局變量和組件實例變量。
這兩個方法的調用參數是客戶端對象(這個客戶端對象具有一個唯一的__ID__)返回一個新的對象.
如果我們給getClientGlobalStorage設置了某個屬性,就可以從任何地方訪問到該屬性值;但是我們如果給getClientLocalStorage對象設置屬性值后,只能在該組件實例中訪問該屬性值,同時也是限制客戶端(唯一的連接__ID__可以訪問)。
那么如何才能從其它客戶端對象訪問 getClientGlobalStorage ?
我們只需要在調用對象的方法的時候包含 __ID__ 屬性就可以,這個 __ID__ 屬性值必須是唯一的。
當我們需要釋放某個組件實例的變量可以用releaseLocalStorage方法
releaseLocalStorage方法在components 組件對象中定義
1 : FCComponent.prototype.releaseLocalStorage = function( client ){
2 : if ( this.clientLocalStorage != null )
3 : delete this.clientLocalStorage[client.__ID__];
4 : }
使用的時候很簡單:
1 : FCMySSComponent.releaseLocalStorage(Client);
建議在用戶斷開連接的時候釋放存儲,當然你可以保留對象,但是要記住每次新的客戶端連接(甚至是之前的同一個用戶)都會得到一個新的客戶端 __ID__ 值,所以對象在以后將不會被再次使用。
1 : //我們通常在服務器端組件連接的時候會定義兩個對象
2 : var cglobal = this.getClientGlobalStorage(client);
3 : var clocal = this.getClientLocalStorage(client);
4 :
5 : //在斷開連接的時候會釋放
6 : this.releaseLocalStorage(client);
FLASH COM學習筆記.23 發布和播放MP3
?
播放MP3文件
我們知道,Flash中默認的流式播放格式是Flv格式,但是在應用程序中,你可以通過客戶端腳本來播放MP3音頻文件和ID3信息,并使用服務器端腳本發布到stream流。
你需要上傳MP3文件到服務器端的/streams/application_instance目錄(Macromedia FCS MX 1.5 在錄制視頻流的時候會自動創建 streams 目錄,如果不存在,你也可以手動創建)。例如你有個名為CDPlayerApp應用程序,你可以上傳MP3文件到/applications/CDPlayerApp/streams/application_instance目錄。
通過設定共享目錄,你還可以在其它應用程序之間共享MP3。
找到Vhost.xml文件中的節點,在中添加需要共享的目錄,如:
foo;c:\data
表示所有含有foo名稱的目錄都會被定向到c:\data目錄,如foo/bar會被定向為c:\data\bar.flv。
詳細的Vhost.xml說明可以參考FlashCom管理手冊中相關部分。
然后,通過Stream.play指令指定播放的路徑和想要播放的MP3文件。為了播放MP3文件,我們需要使用 NetStream對象的play方法,或者使用MC對象的attachAudio方法,特別需要注意的是,在播放文件前面要加上mp3播放標識前綴 mp3:,我們來看代碼示例:
1 : //非共享方式播放
2 : vidObj.attachVideo(mystream);
3 : mystream.play( 'mp3:bolero' );
4 : //文件bolero.mp3在FCS服務器的 C:\mp3_files 目錄下面
5 : //該目錄在vhost.xml中被映射到虛擬目錄 mp3dir
6 : movieObj.attachAudio(mystream2);
7 : mystream2.play( 'mp3:mp3dir/bolero' );
提示: 在使用 NetStream.play 方法的時候如果不指定視頻或音頻格式,會默認為FLV格式, 所以在播放MP3的時候,你必須指定格式播放。也就是說,flv:granada和granada都會播放文件granada.flv,但是mp3:bolero只會播放文件bolero.mp3。注意,這里播放的文件都在服務器端。
要播放MP3文件的ID3信息,必須使用播放前綴id3:并定義相應的回調函數來捕捉id3數據。例如,顯示bolero.mp3文件的ID3 信息:
1 : //displays the ID3 tag of bolero.mp3
2 : mystream.play( 'id3:bolero' );
3 : //callback function to capture the ID3 data. Data will be displayed with
4 : //'info.' preceding the data from the tag, for example, info.songtitle.
5 : mystream.onId3 = function (info){
6 : for (i in info){
7 : trace(i + ':' + info[ i ]);
8 : }
9 : }
支持的MP3 ID3信息的版本
FlashCom server 1.5 支持UTF-8, UTF-16, and ISO-8859-1 格式的 1.0, 2.3和 2.4.版本的ID3信息,并且只支持文本數據,例如:歌曲名、作者、備注和錄制時間等。
使用服務器端腳本
你還可以使用服務器端的Stream對象來播放MP3和獲取MP3文件的長度,更詳細的可以參考服務器端腳本參考中的Stream.play and Stream.length
要刪除MP3文件可以使用Application.clearStreams方法,
下面來看一個例子,通過Stream.play方法來發布MP3:
01 : // Set up the server stream
02 : application.myStream = Stream.get( 'music' );
03 : if (application.myStream)
04 : {
05 : // Publish the MP3 file bolero.mp3 to the stream 'music'
06 : // Use the mp3: prefix in front of the stream name and specify 0 for the
07 : startTime parameter to indicate the server should play the recorded stream
08 : bolero.mp3
09 : application.myStream.play('mp3:bolero', 0, -1);
10 : }
使用 Stream.play 方法來捕獲和播放 ID3 信息,請參考下面的代碼示例:
01 : // Set up the server stream
02 : application.myStream = Stream.get( 'description' );
03 : application.myStream.onId3 = function(info)
04 : {
05 : for (i in info)
06 : {
07 : trace(i + ': ' + info[ i ]);
08 : }
09 : }
10 : if (application.myStream)
11 : {
12 : // Publish the ID3 text tag data of bolero.mp3 to a stream 'description'.
13 : // Use the id3: prefix in front of the stream name and specify 0 for the
14 : startTime parameter
15 : application.myStream.play( 'id3:bolero', 0, -1);
16 : }
?
FLASH COM學習筆記.24 服務器安全(一)
?
FlashCom Server的安全對于應用程序來說很重要,雖然還不致于和PHP、ASP服務器端的安全一樣,畢竟目前服務器端的操作功能還有限。
我們知道,給服務器配置防火墻是較為常用的服務器端安全防范措施,而且也是行之有效的方法。我們會來分析FlashCom Server如何配合防火墻來進行安全保護。
默認的FlashCom服務端口是1935,這就意味著FCS服務器IP地址的1935端口必須設為開放狀態,下面的圖示表示了不同的連接情況。
450) {this.resized=true; this.width=450;}" border=0resized="true">
圖1 沒有任何防火墻的遠程直接連接
450) {this.resized=true; this.width=450;}" border=0 resized="true">
圖2 防火墻沒有開放1935端口的連接情況
450) {this.resized=true; this.width=450;}" border=0resized="true">
圖3 防火墻允許1935端口的連接情況
你還可以配置FlashCom Server接受1935以外的端口,這只需修改配置文件Adaptors.xml 中的項,例如下面的配置可以允許FCS服務器接受來自1935, 8080, 443 和 80端口的RTMP訪問。
<HostPort>:1935, 8080, 443, 80</HostPort>
如果同一服務器上有其它服務在運行,并使用了相同的端口,請不要配置這些端口。
FlashCom 的默認管理端口是1111,更改管理員端口是一個好的建議,如果不想這樣,可以在配置文件Server.xml中修改和項。
最常見的WEB服務端口是80HTTP端口和443HTTPS端口,8080一般用作HTTP服務的備用端口,最簡單的1935端口的解決方法是設置FCS服務器接受80和443端口(假設沒有其它占用),為了監聽1935, 443和 80 端口,可以配置Adaptors.xml文件如下:
<HostPort>:1935, 443, 80</HostPort>
如果要指定某個IP的端口訪問,可以用
<HostPort>XXX.XXX.XXX.XXX:1935, 443, 80</HostPort>
許多情況下,你可能要穿越多個防火墻甚至使用HTTP通道,但是這樣仍然可以正常工作,因為NetConnection對象已經支持該特性。當你使用RTMP協議的時候沒有指定端口號,Flash會嘗試使用1935端口,如果失敗則會嘗試443端口,如果仍然不行,就使用80端口最后嘗試。
看下面的連接代碼:
1 : nc.connect( 'rtmp://host.domain.com/myApp/myInstance' );
為了更好的使用FlashCom服務和安全性考慮,有如下建議:
1. 在同一臺FlashCom服務器上不要使用WEB服務
2. 如果需要請配置Web服務和FlashCom服務不同的IP地址
3. 配置你的Web服務只使用443或8080端口,80端口留給FlashCom
另外一個方案是配置FlashCom服務接受8080端口,連接方式修改為
1 : nc.connect( 'rtmp://host.domain.com:8080/myApp/myInstance' );
當指定了端口號后,Flash只會嘗試指定的端口訪問。
除了rtmp協議之外,FlashCom1.5和FlashPlayer6,0,65,0之后還支持rtmpt協議
1 : nc.connect( 'rtmpt://host.domain.com/myApp/myInstance' );
使用rtmpt協議的時候,我們無須指定端口,Flash會使用80端口連接。其實我們無須使用rtmpt協議,因為默認的rtmp連接方式也會嘗試該種方式的連接。
1 : nc.connect( 'rtmp://host.domain.com/myApp/myInstance' );
當我們使用上面的連接代碼的時候,系統會自動按照下面的順序使用端口和協議。
1 1935 RTMP
2 443 RTMP
3 80 RTMP
4 80 RTMPT?
450) {this.resized=true; this.width=450;}" border=0resized="true">
PS:關于HTTP通道協議
?
FLASH COM學習筆記.25 服務器安全 (二)
?
除了使用防火墻之外,很多企業為了使得網絡更安全,還會使用代理服務器作為內部服務器和因特網之間的中介。
通過和防火墻整合,代理服務器可以防止客戶機直接連接到因特網,所有訪問請求都來自代理服務器,并且可以緩存頁面內容和提升網絡訪問速度。這樣通過代理服務器,防火墻就可以屏蔽所有來自客戶端的直接請求,包括80端口,只有代理服務網可以通過80端口訪問外部網絡。
450) {this.resized=true; this.width=450;}" border=0>
圖1 代理服務器和防火墻的配合使用
在Macromedia的HTTP通道技術之前,在代理服務器之后的客戶機是不能夠連接FlashCom Server,但是現在仍然可以做到。從代理服務器的角度來看,使用RTMPT協議就如同使用HTTP請求一樣,FlashCom Server端的回應也就像是HTTP回應一樣。但是,代理服務器并不能保證請求成功,因為代理服務器會首先讀取緩存。
每次成功的請求在服務器端都會有回應,大致的內容如下:
HTTP/1.1 200 OK
Server: Netscape-Enterprise/6.0
Date: Sat, 24 May 2003 01:09:43 GMT
Content-type: text/html
Etag: 'c96066c3-1-0-1e8'
Last-modified: Tue, 25 Jun 1996 19:11:18 GMT
Content-length: 488
Accept-ranges: bytes
FlashCom Server返回的頭信息不包含Content-type,也就會默認為text/html。
FlashCom Server升級為1.5版本之后,一個引人注目的地方就是重寫了SimpleConnect組件的代碼,當默認的1935端口無法連接時候,增加了額外的特性來加速連接。也就是說,如果我們在使用SimpleConnect組件連接的時候使用不帶端口參數的RTMP協議,那么SimpleConnect組件會嘗試下面的連接方式:
1. 創建一個NetConnection對象并使用默認的1935端口進行常規連接
2. 等待250ms后創建第二個NetConnection對象, 嘗試使用RTMPT方式使用80端口進行連接
3. 接收第一個成功的連接,并關閉和刪除另一個NetConnection對象
嚴格來說,這個不是必須的。事實上,FlashPlayer會依次嘗試使用1935, 443和80端口的RTMP連接,然后再嘗試使用80端口的RTMPT方式連接,但是這樣很耗時間。如果在第一次RTMP連接后,啟用80端口的RTMPT方式可以有效的加速連接過程。我們可以看下SimpleConnect組件中FCSimpleConnectClass類的actualConnect()方法就可以明白Macromedia是怎么處理的。當然,并不是每個人都使用SimpleConnect組件來開發,下面的代碼可以給出一些提示和示例。
001 : // The onConnect function is called when a connection ismade.
002 : function onConnect(nc){
003 : _global.main_nc = nc; // Assign the successful nc to a global variable.
004 : // For test purposes trace out the uri to see which protocol we are using
005 : trace( 'onConnect> ' + nc.uri);
006 : // Create a new onStatus handler for the successful NetConnection object:
007 : main_nc.onStatus = function(info){
008 : // your own onStatus handler code goes here
009 : // to handle errors and other events.
010 : // For testing this just prints out the contents of the informationobject.
011 : trace( '----main_nc.onStatus----' );
012 : for (var p in info){
013 : trace(p + ': ' + info[ p ])
014 : }
015 : }
016 : // Now connect other components and/or initialize your program.
017 : }
018 :
019 :
020 : // The onConnectFailed function is called if a connection cannot be made.
021 : function onConnectFailed(info){
022 : // Examine the info object and
023 : // report why you can't connect.
024 : // This code just traces out the information object.
025 : // Replace it with your own error handling.
026 : trace('----onConnectFailed----');
027 : // Loop through all the properties of the information object.
028 : for (var p in info){
029 : trace(p + ': ' + info[ p ]);
030 : // If the application rejects the connection and passes back
031 : // and application object loop through all its properties too.
032 : if (p == 'application'){
033 : var appObj = info.application;
034 : for (var q in appObj){
035 : trace(' ' + q + ': ' + appObj[q]);
036 : }
037 : }
038 : }
039 : }
040 :
041 : // Create a new NetConnection object that will be used to
042 : // attempt an RTMP connection.
043 : rtmp_nc = new NetConnection();
044 : // Create an onStatus handler that will dispose of the rtmpt_nc
045 : // NetConnection object if this connection succeeds first.
046 : rtmp_nc.onStatus = function(info) {
047 : this.pending = false;
048 : if (info.code == 'NetConnection.Connect.Success') {
049 : if (rtmpt_nc.pending) {
050 : rtmpt_nc.onStatus = null;
051 : rtmpt_nc.close();
052 : rtmpt_nc = null;
053 : clearInterval(connectionID);
054 : }
055 : onConnect(this);
056 : } else
057 : if (! rtmpt_nc.pending){
058 : onConnectFailed(info);
059 : }
060 : }
061 :
062 : // Create a new NetConnection object that will be used to
063 : // attempt an RTMPT connection.
064 : rtmpt_nc = new NetConnection();
065 : // Create an onStatus handler that will dispose of the rtmp_nc
066 : // NetConnection object if this connection succeeds.
067 : rtmpt_nc.onStatus = function(info) {
068 : this.pending = false;
069 : if (info.code == 'NetConnection.Connect.Success') {
070 : if (rtmp_nc.pending) {
071 : rtmp_nc.onStatus = null;
072 : rtmp_nc.close();
073 : rtmp_nc = null;
074 : }
075 : onConnect(this);
076 : } else
077 : if (! rtmp_nc.pending){
078 : onConnectFailed(info);
079 : }
080 : }
081 :
082 : // Mark both nc objects as pending.
083 : rtmp_nc.pending = true;
084 : rtmpt_nc.pending = true;
085 :
086 : // Try to connect with rtmp right away:
087 : rtmp_nc.connect('rtmp://host.domain.com/myApp/myInstance', userName,password);
088 :
089 : // Setup an interval to try rtmpt in 400 milliseconds:
090 : connectionID = setInterval(connectRTMPT, 400);
091 :
092 : // Clear the interval and try to connect with RTMPT when this function iscalled.
093 : function connectRTMPT(){
094 : clearInterval(connectionID);
095 : rtmpt_nc.connect('rtmpt://host.domain.com/myApp/myInstance', userName,password);
096 : }
097 : //You can modify this code to try other ports. For example, if you can'tuse port 80 and want to try port 8080, use this code:
098 : function connectRTMPT(){
099 : clearInterval(connectionID);
100 : rtmpt_nc.connect('rtmpt://myHost.myDomain.com:8080/myApp/myInstance',userName, password);
101 : }
?
FLASH COM學習筆記.26 服務器安全(三)
?
服務器加密傳輸
在瀏覽器中運行Flash的時候,macromedia通過RTMPT方式使用HTTP服務來交互數據。自從瀏覽器支持SSL方式后,一個更安全的加密HTTPS通道也隨之而來了。你可以使用RTMPS方式來連接:
1 : nc.connect('rtmps://myHost.myDomain.com/myApp/myInstance');
當你指定RTMPS作為連接方式時,系統默認使用443端口進行連接。但是FlashCom MX Server1.5并不支持SSL,所以要使用SSL方式加密交互數據并不可能,所以我們需要使用其它的方式來實現,大致有三種方法:
1. 使用第三方的加密傳輸軟件(如stunnel, http://www.stunnel.org/),用來監控443端口,并在1935和443端口之間來回傳輸未經加密的數據。
450) {this.resized=true; this.width=450;}" border=0>
2. Flash文件直接連接到另外一臺安裝有stunnel的服務器,并且配置第二臺服務器連接FlashCom Server,其間傳輸未經加密的數據。這種方式,安裝有stunnel的服務器充當了中間層服務器。
450) {this.resized=true; this.width=450;}" border=0resized="true">
需要注意的是:stunnel監聽443端口的加密數據,然后通過1935端口傳輸未經加密的數據給另一臺FlashCom Server。在這種方式下,Flash連接的服務器必須是stunnel,而不是連接到flashCom Server,例如,假如stunnel服務器的域名是stunnel.mydomain.com,那么正確的連接代碼應該寫成:
rtmps://stunnel.mydomain.com/myapp/myinstance
3. 在網絡中使用專門的SSL加速器(通常使用交換機來完成),來接收加密數據并解密后傳輸給FlashCom Server。
450) {this.resized=true; this.width=450;}" border=0resized="true">
在以上三種方法中,第三種方法到目前為止應該說是最好的解決方法,雖然花費昂貴一些。專門的網絡SSL硬體解決比服務器端的安裝配置要來的簡便和高效。
SSL硬件加速器通過網絡交換機工作,不需要在WEB 服務器上加載SSL進程,配置stunnel服務更是一個挑戰性的工作。
PS:其它關于FlashCom安全方面的文章
1. a security checklist for Macromedia Flash Communication Server MX.
2. Macromedia Flash Communications Server MX security overview
3. Updates to the SimpleConnect component
4. Securing Macromedia Flash Communication Server
?
FLASH COM學習筆記.27 服務器安全問答
?
?什么是FlashCom Server?
(略)
?什么是FlashCom應用程序
?也就是一個和Flash Communication Server交流的Flash應用程序,可以是一對一,也可以是一對多,甚至多對多的模式,還可以用作智能化的機器人交流,例如進行實時的數據傳送和通知。
一個典型的FlashCom應用程序包含:
1 : 應用程序入口:網頁或獨立應用程序,通常包含一些SWF文件
2 : 客戶端swf文件:可以是網頁或獨立應用程序形式,一般包含了FlashCom應用程序的UI,也包含程序執行的一些客戶端腳本
3 : 服務器端代碼和數據:服務器端的腳本
4 : 應用程序服務器:包含其它PHP、ASP或CFML腳本的服務器
?FlashCom使用的網絡協議是什么
?Flash使用RTMP(the Real-time Messaging Protocol )協議作為客戶端和服務器端的傳輸協議,這是一個專門為高效傳輸視頻、音頻和數據而設計的TCP/IP 協議,使用RTMP協議傳輸的數據是未經加密的,包括用戶名和密碼等認證信息。
雖然RTMP協議不安全,但是也可以通過使用支持SSL的服務器來實現安全傳輸。
?有哪些方式控制用戶訪問
?FCS支持多種方式的用戶連接認證。
1. 無須用戶名和密碼的訪問(不推薦)
2. 基本認證:通常使用用戶名和密碼,經由RTMP方式傳輸,在服務器端驗證
3. 入場券認證:客戶端通過入場券交由服務器端認證,并且只能在一段時間之內使用。
4. IP認證:在服務器端配置允許訪問IP或域名
?如何控制連接用戶數
?在服務器端可以使用腳本統計目前連接用戶數,并可以拒絕超過用戶數之外的連接。
?如何保存用戶數據隱私
?用戶數據以共享對象的方式保存,可以保存在用戶端和服務器端,可以是臨時的也可以是永久的。應用程序只能訪問自己相關的共享對象,但是共享對象的存儲使用未經加密的二進制文件,其中有些安全方面的隱患。
?如何控制對主機資源的使用
?應用程序之間不能夠相互訪問文件或其它資源,每個應用程序使用唯一的目錄。管理員可以設置每個應用程序的帶寬和使用磁盤空間,可以防止某個應用程序的資源消耗過大。
?網絡適配器、虛擬主機和應用程序的關系
?FCS支持多個網絡適配器,除此之外,還可以給每個適配器配置多個虛擬主機目錄,每個虛擬目錄又可以運行應用程序實例。例如,相同的視頻聊天應用程序的不同實例之間是不能交互數據的,應用程序總是運行在同一個虛擬主機上。
?如何配置服務器端
?合適的服務器配置是保障應用程序安全的關鍵,下面一些地方是管理員可以配置的,也是和安全相關的:
01 : 管理員帳號和密碼
02 : 允許或禁止的IP地址或域名
03 : 性能優化的參數設置
04 : 連接訪問的IP和偵聽端口
05 : 服務器訪問和應用程序事件日志
06 : 服務器端腳本的優化
07 : 應用程序的帶寬性能
08 : 客戶端連接到應用程序的帶寬占用
09 : 用于視頻、數據和應用程序存儲的目錄
10 : 應用程序實例、視頻流和共享對象的限制
合理的FlashCom服務器端和客戶端應用程序的開發和配置能夠使得應用程序更安全,更詳細的安全建議請參考其它相關文章。
FLASH COM學習筆記.28 服務器安全建議
把FlashCom開發和配置方面的安全建議作個總結:
01 : 使用安全的管理員帳號和密碼設定,不要使用admin和administrator之類的用戶名,密碼最好包含數字和字符,長度不要少于8位;
02 : 在Server.xml文件中配置和標記,限制可以連接管理應用程序的客戶端;
03 : 更改默認的管理控制臺端口,并配置防火墻阻止訪問;
04 : 在Vhost.xml文件中配置和標記,限制可以連接該虛擬主機的客戶端;
05 : 如果你的應用程序沒有創建或使用視頻流,設置Vhost.xml中的標記值為0;
06 : 根據你的要求設置Vhost.xml中的標記為on或off;
07 : 如果需要更改內存分配、垃圾回收頻率或其它相關設置的時候,檢查Server.xml文件中的標記;
08 : 如果你的應用程序連接了多個服務器,請確認設置了Server.xml文件中的標記;
09 : 反復檢查Vhost.xml文件中的標記,確保你沒有偵聽多余的端口,并確認防火墻正常啟用或屏蔽了這些端口;
10 : 在Adaptor.xml 文件中配置和標記,限制可以連接到應用程序的域名和IP地址;
11 : 最終發布的客戶端程序不要顯示出應用程序名稱以及服務器地址等信息,最好是硬編碼在源文件中(雖然還是不安全);
12 : 始終在服務器端驗證客戶端連接的提交地址是否合格,這樣可以防止使用自己的客戶端程序來連接相同的應用程序;
13 : 在你的Flash文件中添加基本的握手代碼,防止客戶端有欺詐行為,因為Flash數據傳輸沒有加密;
14 : 檢查服務器端腳本移除所有調試代碼或其它不需要的代碼;
15 : 移除所有的不再使用的外部或舊版腳本;
16 : 在Vhost.xml中設置標記指明應用程序的位置,這個路徑應該不能通過WEB方式或其它方式訪問;
17 : 刪除不必要的應用程序;
18 : 刪除安裝Macromedia Flash Communication Server MX后自帶的應用程序范例;
19 : 設置Vhost.xml文件的標記指明視頻流文件的存儲路徑,這個路徑應該不能通過WEB方式或其它方式訪問;
20 : 設置Vhost.xml文件的標記允許合適數量的共享對象,其中有些參數值會受服務器授權的限制;
21 : 設置Vhost.xml文件的屬性來限制對虛擬主機的連接;
22 : 在Application.xml文件中的段標記中更改屬性防止應用程序死循環;
23 : 檢查Application.xml中的所有屬性;
24 : 所有的web文件(HTML, SWF等)應該放置到你的web服務器目錄,如果同一臺服務器也是FlashCom服務器的話,要確保分開;
25 : 刪除你的web目錄下面的所有相關應用程序文件或資源(尤其是fla文件);
?
FLASH COM學習筆記.29 服務器日志
?
在管理FlashCom MX Server的時候,一件非常重要的事情就是收集運行在服務器上的不同應用程序以及應用程序實例的狀態信息。在大多數的服務器環境中,服務器日志對于管理和故障檢查來說是非常有用的工具。
FlashCom Server在同一時間可能同時運行著多個應用程序以及應用程序實例,我們需要了解多少用戶連接和各個應用程序或應用程序實例消耗了多少帶寬。服務器管理API提供了靈活的方法可以收集這些信息。我們來了解下不同的服務器日志記錄方法和FlashCom服務器管理API提供的示例日志程序,這些日志程序和管理控制臺應用程序類似。
一、日志類型
<strong><span style="color: orange\">1. 服務器訪問日志</span></strong>:服務器把所有的訪問日志記錄在名為access.flv的流文件中,我們可以通過Vhost.xml中的<RecordAccessLog>標記項來控制是否記錄,如果設置為true,服務器就會保存訪問信息到access.flv文件中,該文件一般位于應用程序目錄的admin/streams/logs 目錄下。
<strong><span style="color: orange\">2. 應用程序調試日志</span></strong>:服務器端腳本經常會使用tracer命令來調試應用程序,我們可以通過Applications.xml中的<RecordAppLog>標記項來控制是否記錄該調試信息,如果設置為True,服務器會保存調試信息到admin/streams/logs/application/YourAppName/目錄下面并且使用和應用程序實例名相同的文件名。
<strong><span style="color: orange\">3. 服務器端腳本日志</span></strong>:服務器管理應用程序是一個特殊的應用程序,允許控制和訪問服務器的相關信息。服務器端腳本可以訪問這些數據并保存下來以便以后恢復。
不管有多少日志信息存儲在服務器上,它有可能必須被恢復,我們需要分析和格式化成日志信息供以后使用。例如,可以通過一個特殊的客戶端swf文件來訪問這些日志,下載日志信息和創建報告。
有兩個范例日志程序:Flash Communication Server Log Reader和FlashCommunication Server Bandwidth Monitor (Flogger)
二、 Flash Communication Server Log Reader
該應用程序用于讀取FlashCom Server日志記錄。允許管理員收集服務器端的使用報告,也可以定制服務器端日志記錄情況。使用之前,你最好熟悉FlashCom Server的安裝、配置和管理。
[ 下載 ]
三、 Flash Communication Server Bandwidth Monitor (Flogger)
該應用程序用于監視服務器帶寬使用情況。
[ 下載 ]
?
FLASH COM學習筆記.30 服務器端ActionScript的命名和搜索路徑
?
翻譯自官方的FlashCom TechNote 譯者:liu21st(晴天的魚)
原文出處:mm/serverside_names.htm
當FlashComServer端應用程序加載的時候,服務器會檢查服務器端的ActionScript文件。
該文件可以位于application目錄下或者其scripts子目錄下,并且可以有多種命名方式。
通常,都放在application目錄的應用程序目錄下面,名稱為main.asc。這是FlashCom Server默認的方式,但是,為了安全和管理起見,我們應該另外命名以更好的區分不同的應用程序。因此,使用<application_name>.asc的命名是一個良好的習慣,我們甚至可以使用js作為文件擴展名。
下面是服務器端Actionscript文件的搜索順序:
1 : 位于/scripts目錄下面的main.asc文件
2 : 位于目錄下面的main.asc文件
3 : 位于/scripts目錄下面的main.js文件
4 : 位于目錄下面的main.js文件
5 : 位于/scripts目錄下面的.asc文件
6 : 位于目錄下面的.asc文件
7 : 位于/scripts目錄下面的.js文件
8 : 位于目錄下面的.js文件
在上面的搜索路徑中,<appName>是指應用程序的目錄名稱
一般地,對于開發模式,該目錄位置在C:\inetpub\wwwroot\flashcom\applications\<appName>
對于產品模式默認位置為 C:\Program Files\Macromedia\Flash CommunicationServer\flashcom\applications\<appName>.
如果是Linux環境,應該是/opt/macromedia/fcs/application/<appName>
加載另外的Actionscript文件
如果要在服務器端ActionScript文件中加載另外的文件,需要使用Load命令
如load('logic.asc' );
FlashCom server 首先會在當前目錄搜索logic.asc文件,然后再搜索 Application.xml (位于C:\Program Files\Macromedia\Flash Communication ServerMX\conf\_defaultRoot_\_defaultVHost_\Application.xml或/opt/macromedia/fcs/conf/Application.xml)中<ScriptLibPath>標記指定的目錄。
對于開發模式,該標記默認為
1 :
如果要指定多個搜索路徑,可以用分號隔開
?
FLASH COM學習筆記.31 服務器集群和負載均衡
?
本篇主要講述在進行FCS開發過程中如何使用多個視頻服務器來做集群服務和負載均衡處理。
在FCS的應用過程中,帶寬消耗是一個很嚴重也是很現實的問題,好的解決方法就使用多個服務器進行負載均衡,也就是說使用服務器集群技術。
有三種服務器集群的方案:
1 使用專門的主服務器來連接多個子服務器
450) {this.resized=true; this.width=450;}" border=0>
2 每臺服務器既可以作為主服務器也可以充當子服務器
450) {this.resized=true; this.width=450;}" border=0>
3 每臺服務器都作為主服務器
450) {this.resized=true; this.width=450;}" border=0>
那么到底哪種方式最好呢?這取決與你所做的應用,每種方式都可以滿足各自不同的需要。
根據FCS應用程序的架構和流媒體的特性,為了最低限度的減少數據丟失以及數據同步問題,第三種方案不失為一種好的方案。
舉個例子,假如你有個應用程序同時有1000在線用戶需要連接FCS服務,而你每臺服務器的帶寬僅僅能夠滿足500個用戶的需求,或許你會說為什么不用單獨一臺服務器來作負載均衡控制,答案很簡單:多余。況且讓我們設想一下,如果哪天這臺服務器想要休息一下,那么你的應用會怎么樣?
因此,為了安全起見,使用多個主服務器的方式最適合,至少不會發生上面所說的問題。
集群方式確定了,那么在開發過程中如何使用呢?
也有兩種方式,取決你所做的應用:
1、在不同服務器之間同步
2、不同服務器之間不進行同步(嚴格的說不能說是集群技術)
其實兩種方式的差異不用說也知道,但如果只是想減輕帶寬負荷,并不想在多個服務器之間保持數據一致就可以采用第二種方式。
關于第一種方式,Jake Hilton給出了比較好的解決方式,在此也不多說,簡單說明下。原理就是在進行服務器連接、發布和設置操作的時候循環對每個在線的服務器進行操作。
例如:
//serverArray 是連接服務器數組
for(var i in serverArray){
this['nc'+i] = new NetConnection();
this['nc'+i].connect(serverArrayIn[i]);
this['nc'+i].onStatus = function(objIn){ _self.ncStatus(objIn) };
liveServers.push(i);
?}
在onStatus方法中會檢查在線服務器,調用pingBack方法得到liveServers的值。
在應用程序的Main.asc文件中添加如下代碼:
?
Client.prototype.serverPing=function(srvId){
?
? return { 'serverId':srvId,'serverName':application.hostname };
?
?}
?
Client.prototype.setSoObject=function(soName){
?
? setUpSharedObject(soName);
?
?}
?
Client.prototype.getSoValue=function(soName,propName){
?
? return eval(soName).getProperty(propName);
?
?}
Client.prototype.setSoValue=function(){?//soName,propName,propVal
? eval(arguments[0]).setProperty(arguments[1],arguments[2]);
?}
function setUpSharedObject (soName) {
? if(!this[soName]){
??? trace('setting up shared object '+soName);
??? this[soName]=SharedObject.get(soName,true);
?? }
?}
把Main.asc文件放到你的FCS應用程序目錄下面后重啟應用。
客戶端測試代碼示例:
?
import com.sitename.MultiConnection
?
mc = new? MultiConnection();
?
mc.connect(['rtmp://server1.com/test','rtmp://server2.com/test']);
?
mc.onStatus = function(objIn){
?
? trace(objIn.code);
?
? if(objIn.code == 'NetConnection.Setup.Success'){
?
??? mc.sharedObjectSetup ('info_so',true);
?
??? mc.setNetStreams();
?
??? myMic = Microphone.get();
??? mc.attachAudio(myMic);
??? mc.nsStatus=function(objIn){
????? trace(objIn.code);
???? }
??? mc.publish ('webCastName','live');
?? }
?}
mc.info_so_sync = function(){
? trace('so synced');
?}
代碼連接多個服務器,并且在每個服務器上創建共享對象info_so,并且通過info_so_sync 方法來同步。
下載完整的類和示例程序
第二種方法就更簡單了,把實現思路說明一下。
在客戶端判斷不同的聊天室或者不同的用戶ID,轉向不同的FCS服務器。服務器端代碼不需要任何修改,客戶端只需做一個引導程序
?
Flash Media Server學習日記一
?
終于知道怎么做流式播放了...
不知道是我問的問題太低級還是沒表達清楚,走了N個論壇都沒人回帖子.
后來實在沒辦法了,只能用GOOGLE翻譯國外的頁面慢慢研究了...
經過倆小時的搜索查看,沒白搞.終于理出FLASH MEDIA SERVER的目錄結構了...
我的FLASH MEDIA SERVER安裝在D盤.
D:\Program Files\Macromedia\Flash Media Server 2\
打開FMS的目錄,進到applications目錄,新建一個名叫Tensharp的目錄.(就是我的測試站點,嘿嘿.)
然后在Tensharp里新建個名字叫Streams的目錄,再在Streams里建個_definst_目錄.
FLV文件就放在這里...在FLASH里讀的路徑是 rtmp:/tensharp/life(注意,這里沒FLV文件的后綴名.)
打開FLASH,新建一個文檔.
新建一個視頻對象取名為MyVideo
在第一楨上按F9,輸入:
?
var MyNetConnection = new NetConnection ();
MyNetConnection.connect ("rtmp:/tensharp");
MyNetConnection.onStatus = function (TeN) {
?if (TeN.code == "NetConnection.Connect.Success") {
? trace ("服務器開放中...");
?}
};
var MyNetStream = new NetStream (MyNetConnection);
MyVideo.attachVideo (MyNetStream);
MyNetStream.setBufferTime (5);
MyNetStream.play ("life");
?
先前做完那個東西感覺FMS并不是很難..比當時第一次用FLASH + XML做東西
容易了許多..可能是還沒找到套路吧.
總結
以上是生活随笔為你收集整理的关于Flash Media Server的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机毕业设计Python+uniapp
- 下一篇: Jetson Orin 平台MAX929