flash player10.1 + FMS4中的p2p功能
在fms4以前Adobe只允許在stratus中才能使用p2p功能。令人高興的是,在最新發布的fms4中,p2p功能已經集成進來了,這將給實時視頻類的應用帶來更高的效率,adobe這次很給力!
為了使用p2p,開發用的flex sdk至少要4.1以上(當然最高版本是代號為hero的4.5版本,可從adobe的官網下載),另外還需要fms4(同樣可從adobe官網下載開發版本)。
先上完整代碼吧:
package {import fl.controls.Button;import fl.controls.Label;import fl.controls.TextArea;import flash.display.Sprite;import flash.events.MouseEvent;import flash.events.NetStatusEvent;import flash.net.GroupSpecifier;import flash.net.NetConnection;import flash.net.NetGroup;import flash.net.NetGroupReplicationStrategy;import flash.text.TextFormat;public class p2p_HelloWorld extends Sprite {private var _lbl:Label;private var _btnAddToWant:Button;private var _btnGenData:Button;private var _btnAddToHave:Button;private var _txtObj:TextArea;private var _txtOutput:TextArea;private var _data:Vector.<String>;private var _dataLength:uint = 100;private var _nc:NetConnection;private var _ng:NetGroup;private var _spec:GroupSpecifier;private var _server:String = "rtmfp://localhost/HelloServer";private var _groupName:String = "myGroup";private var _connected:Boolean = false;public function p2p_HelloWorld(){init();}private function init():void {this._btnAddToWant = btnAddToWant;this._btnAddToHave = btnAddToHave;this._btnGenData = btnGenData;this._txtObj = txtObj;this._txtOutput = txtOutput;this._lbl = lbl;var style:TextFormat = new TextFormat("宋體", 12, 0x000000,false,false,false,null,null,null,null,null,null,5);this._btnAddToHave.setStyle("textFormat", style);this._btnAddToWant.setStyle("textFormat", style);this._btnGenData.setStyle("textFormat", style);this._txtObj.setStyle("textFormat", style);this._txtOutput.setStyle("textFormat", style);this._lbl.setStyle("textFormat", style);this._btnGenData.addEventListener(MouseEvent.CLICK, _btnGenData_Click);this._btnAddToHave.addEventListener(MouseEvent.CLICK, _btnAddToHave_Click);this._btnAddToWant.addEventListener(MouseEvent.CLICK, _btnAddToWant_Click);//先連接到服務器_nc = new NetConnection();_nc.addEventListener(NetStatusEvent.NET_STATUS, _nc_Net_Status);_nc.connect(_server);output("正在連接 " + _server + " ...");}private function _nc_Net_Status(e:NetStatusEvent):void {output(e.info.code);switch (e.info.code){case "NetConnection.Connect.Success": //連接成功后,要設置NetGroupthis._spec = new GroupSpecifier(this._groupName); _spec.serverChannelEnabled = true;//設置允許創建到服務端的通道_spec.objectReplicationEnabled = true;//允許對象復制_ng = new NetGroup(_nc, _spec.groupspecWithAuthorizations());_ng.addEventListener(NetStatusEvent.NET_STATUS, _nc_Net_Status);break;case "NetGroup.Connect.Success":_connected = true;_ng.replicationStrategy = NetGroupReplicationStrategy.LOWEST_FIRST;//設置數據塊傳輸時,先傳遞索引號最小的塊break;case "NetGroup.Replication.Fetch.SendNotify": //每當"接收方"有數據到達(但尚未開始接收)時,將觸發此處理output(" -->通知:數據塊 " + e.info.index + " 即將被接收");break;case "NetGroup.Replication.Fetch.Failed": //“接收方”有數據接收失敗時,將觸發此處理output(" -->錯誤:數據塊 " + e.info.index + " 接收失敗");break;case "NetGroup.Replication.Fetch.Result": //“接收方”每次成功接收到數據時,觸發此段處理output(" -->數據塊 " + e.info.index + " 已成功接收,值:" + e.info.object);_ng.addHaveObjects(e.info.index, e.info.index); //接收完成以后,將接收到的數據加入“待發送對象列表"中,這樣人越多,傳輸越穩定,速度也越快 if (_data == null) {_data = new Vector.<String>(this._dataLength);}_data[e.info.index] = e.info.object.toString();//說明全部接收完了if (e.info.index == this._dataLength - 1) {for (var i:int = 0; i < _dataLength; i++){_data[i] = "這是數據 " + i.toString();this._txtObj.appendText("index:" + i.toString() + ",data:" + _data[i] + " | ");}}break;case "NetGroup.Replication.Request": //每當有數據傳輸請求時,“提供方”將觸發此處理_ng.writeRequestedObject(e.info.requestID, _data[e.info.index]);//這里才是真正的響應“接收方",將指定的數據發送過去output(" -->數據塊 " + e.info.index + " 請求被發送,本次請求ID:" + e.info.requestID);break;default:break;}}//初始化生成數據private function _btnGenData_Click(e:MouseEvent):void {this._txtObj.text = "";if (_data==null){_data = new Vector.<String>(this._dataLength);}for (var i:int = 0; i < _dataLength; i++){_data[i] = "這是數據 " + i.toString();this._txtObj.appendText("index:" + i.toString() + ",data:" + _data[i] + " | ");}}//將生成的初始數據,添加到待發送的“列表”中private function _btnAddToHave_Click(e:MouseEvent):void {this._ng.addHaveObjects(0, _dataLength - 1);}//請求接收數據private function _btnAddToWant_Click(e:MouseEvent):void{this._ng.addWantObjects(0, _dataLength - 1);}//輸出結果private function output(s:String):void {this._txtOutput.appendText(s + "\n");}}}在這段代碼中我們看到了一個全新的NetGroup對象,要使用p2p,“接收方”與“接收方”必須先加入到“相同名稱"的NetGroup中。而且要發送的數據,必須分解有順序的一塊一塊(通常用有序數組來保存這些數據塊),然后"發送方"調用addHaveObjects方法設置待發送的數據塊,而"接收方"則調用addWantObjects請求需要接收的塊。
一旦"接收方"調用了addWantObjects方法后,"發送方"便會進入"NetGroup.Replication.Request"狀態,此時"發送方"響應"接收方"的請求,將需要的數據塊以udp協議發送過去,然后“接收方”會收到"NetGroup.Replication.Fetch.SendNotify"的數據到達通知,如果成功接收,將進入“NetGroup.Replication.Fetch.Result”狀態,全部接收完成后,開發人員可根據需要將這些塊重新合并成原始對象。
處理過程示意圖如下:
文中代碼最終的運行截圖:
測試方法:發送方先點擊“生成初始數據”,然后點擊“添加要發送的數據”,最后接收方點擊“接收數據”
此外,如果多開幾個"接收方",可以驗證一下“接收方”收到數據后是否能變成數據提供者,向其它接收方提供數據,也就是所謂的p2p中"人越多,速度越快,傳輸越穩定"的現象
但是,FMS4中的p2p也不是完美無缺,實際測試下來,目前尚不能打洞,即所有peer端如果在同一個網段,傳輸是正常的,但是如果不是同一個網段則無法進行p2p。
不過,如果參與p2p的機器越多,接收到數據的客戶端根據文中的代碼處理,也可以變成發送方,這表示有可能本來在同一個網段的其它用戶原本沒有數據來源,但是只要本網段有一個用戶接收到數據后(比如這個用戶有多重網絡),本網段的其它用戶也能接收數據了,這在一程度上能解決打洞的矛盾。
示例源文件下載:http://files.cnblogs.com/yjmyzz/p2pTest.7z
轉載于:https://www.cnblogs.com/yjmyzz/archive/2010/11/25/1888072.html
總結
以上是生活随笔為你收集整理的flash player10.1 + FMS4中的p2p功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 处理2D图像和纹理——显示文字
- 下一篇: SharePoint 2007/2010