1. 程式人生 > >Flash Player 10中使用RTMFP開發P2P應用的Cirrus服務

Flash Player 10中使用RTMFP開發P2P應用的Cirrus服務

Adobe Flash Player 10 和 Adobe AIR 1.5 引入了一個新的通訊協議——Real-Time Media Flow Protocol 即實時媒體流協議,簡稱RTMFP。它具有低延遲、對等的端到端能力、安全性和可擴充套件性,尤其適合於開發實時協作的應用,不僅提供優秀的使用者體驗還降低了 操作者的開銷。

早期的Flash Player版本採用RTMP並且需要FMS 對於互動式的協作應用(例如:adobe Acrobat Connect Pro)或者音/視訊流服務。雖然RTMP是一很優秀的選擇,對於流媒體、共享物件或遠端操作,限定於實時互動式的音視訊通訊需求

為了使用RTMFP,Flash Player終端必須連線到支援RTMFP的伺服器,如:代號Cirrus(以前稱為Stratus)的服務或FMS4,Cirrus是一個提供集合點服 務的主機,並輔助Flash Player終端之間建立通訊帳號。不像FMS,Cirrus不支援媒體中繼(media relay)、共享物件、指令碼等。所以使用Cirrus,只能開發Flash Player終端之間直接通訊的應用。

Flash Player已經是WEB線上視訊分發市場的領袖。在引入RTMFP和高階媒體壓縮技術後,Flash Player成為實時通訊領域的領袖。

這篇文章,首先強調了在實時通訊應用程式中採用RTMFP的好處。之後,敘述了管理直接端到端RTMFP連線的AS3 API。最後,介紹了VideoPhone 應用樣例。

RTMFP的優勢:
RTMFP是一個在Flash Player 10 和AIR 1.5 中引入的全新通訊協議。與RTMP的主要不同在於:RTMP是基於TCP並專門用於以前的Flash Player版本,而RTMFP建立於UDP之上。

雖然TCP提供了可靠的資料傳送(對檔案傳輸、電子郵件等非常適合),但它不能提供絲毫的端到端延遲保證。TCP通過在指定時間內重發丟失資料實 現可靠的資料傳送。因為實時通訊最重要的目標之一是最小化端到端的延遲(100ms的延遲可能致使會話不能使用),TCP並不適合。傳送錯誤適應能力和恢 復能力是絕大多數高階音訊視訊壓縮技術的必需的構成部分,例如已經在Flash Player 10中支援的Speex音訊和H.264視訊編碼。因此不需要TCP提供的可靠傳輸。因此將提供高效而快速的資料傳送的UDP,用於嚴格追求最小化端到端 延遲的實時協作應用,是為人所受的。另外UDP優於TCP的地方在於,它讓端到端對等,它可以讓位於NATs之後的兩個客戶端直接傳送資料。

與RTMP比較,RTMFP在實時通訊方面具有以下優勢:

低延遲:由於RTMFP建立於UDP之上,它為實時通訊提供了最小的延遲。最重要的是RTMFP同時提供了可靠和不可靠兩種傳輸服務。當在兩個 Flash Player例項之間傳送資料時(如:用NetStream.send()方法),採用可靠傳輸。當傳送Speex音訊例項時,採用不可靠傳輸,提供最小 化的延遲。
端到端的媒體傳輸:不需要通過中轉伺服器,即可在兩個Flash Playerp例項之間傳送媒體。RTMP會將所有資料傳送到Flash Medai Server,RTMFP不僅最大限度地降低了端到端的延遲,而且還省掉了連線到中間資料轉接的環節,以至於具有極強的可擴充套件部署能力。
優化資料:傳送音訊資料具有比視訊和其他時間非關鍵資料更高的優先級別。這意味著可以在較緊張的頻寬通訊上增強使用者體驗。
較之前版本,這些功能為實時通訊帶來極大的益處,極大提升了使用者體驗。

防火牆穿越
RTMFP建立於UDP之上,UDP能讓兩個客戶端直接連線,即使它們位於NAT或防火牆之後。為了能讓RTMFP正常工作,你必須允許防火牆的對外UDP傳送。大部分使用者或SOHO防火牆、多數企業防火牆都關閉了UDP傳送功能。

一種解決方案是配置Flash Player用TURN代理。Flash Player支援未經認證的IETF因特網草案。如果網管配置TURN代理為允許外出UDP,可以在mms.cfg中增加一行配置Flash Player。

RTMFPTURNProxy=ip_address_or_hostname_of_TURN_proxy

直接UDP傳送總是嘗試,TURN代理只是備用:用於UDP傳送不能在Flash Player和Cirrus之間或Flash Player終端之間流動時。

即使你的防火牆打開了對外UDP傳送,也可能由於綜合防火牆不能建立端到端的對等連線。當一個終端位於“均衡防火牆”之後時,也許不能進行端對端通訊。(對於分級防火牆,請參閱   )在這種情況下,你可以使用TURN代理輔助防火牆傳輸。

Cirrus 服務
Flash Player 例項要與另一個例項通訊,就必需連線到Cirrus服務(使用rtmfp://p2p.rtmfp.net)。 Cirrus是一個幫助主持Flash Player例項之間進行聯絡會合的服務,即使它們都位於NATs之後。雖然連線到Cirrus服務非常類似於連線到FMS,但Cirrus不提供任何 FMS的特有功能(媒體延遲、共享物件、遠端等)。Flash Player終端在通訊期間必須保持與Cirrus服務的連線。為了使用Cirrus,需要一個開發key,這個可以在建立Adob Developer ID時生成。
在FMS 4中可以使用RTMFP支援。FMS可以讓Flash Player 9 或早期客戶端(用RTMP)與Flash Player 10 客戶端通訊。

安全
RTMFP提供了可靠的終端之間的通訊。它採用128位AES加密Key,協商採用Diffie-Hellmann交流方式。不過,它不能提供像 SSL或RTMPS一樣強的終端身份認證。為了幫助終端身份認證,RTMFP和ActionScript 對應用開發者公開安全隨機數。要保證兩個通訊的Flash Player終端的隨機數相匹配。終端使用者可通過校驗這些隨機數,以確保在傳輸過程中沒有受到攻擊。這些隨機數也可以用於開發key連續機構。

值得注意的是Flash Player只能將你允許的麥克和攝像頭髮送到其他的Flash Player終端。

ActionScript 3 API supporting RTMFP

為了支援 RTMFP Flash Player 10 中提供了一些新的 AS 3 API 。連線到 Cirrus 服務並建立類似於 FMS 下的端到端的媒體流。請注意,你必需在 Flash Professional CS4 或更新版本)或者 Flash Builder 4 中使用 AS 3 ,目標設定為 Flash Player 10 AIR 1.5

正如我之前所說,你需要先連線到 Cirrus 服務。

private const CirrusAddress:String = "rtmfp://p2p.rtmfp.net";

private const DeveloperKey:String = "your-developer-key";

private var netConnection:NetConnection;

netConnection = new NetConnection(); netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnectionHandler); netConnection.connect(CirrusAddress + "/" + DeveloperKey);

當你用

Adobe Developer Connection 帳戶登入到 Cirrus beta 服務站點上時,會分配一個開必 key

當成功連線到 Cirrus 上時,你獲取一個 NetConnection.Connect.Success 事件。有幾個連線失敗的可能原因。如果你提供一個無效的開發key ,或者指定了錯誤的Cirrus 地址,你會收到 NetConnection.Connect.Failed 事件。如果你的防火牆鎖定了對外UDP 傳送,你會在90 秒超時後,收到 NetConnection.connect.Failed 事件。

在成功建立與 Cirruse 服務的連線後,將分配一個唯一的 256 peer ID 給你。為了接收你釋出的音訊、視訊流,其它的 Flash Player 終端必需知道這個 peer ID 。怎樣在相關 Flash Player 終端間交流這些 peer ID ,屬於 Flash Player Cirrus 服務範圍之外。為了交換 peer ID ,可以用 XMPP 服務或一個簡單的 WEB 服務,像 Video Phone 樣例一般。

Flash Player 例項之間的直接通訊要使用單向 NetStream 通道。如果你想要兩個音訊會話,每一個 Flash Player 都必須建立一個傳送 NetStream 和一個接收 NetStream

首先,建立一個傳送流。

private var sendStream:NetStream;

sendStream = new NetStream(netConnection, NetStream.DIRECT_CONNECTIONS); sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler); sendStream.publish("media");

sendStream.attachAudio(Microphone.getMicrophone()); sendStream.attachCamera(Camera.getCamera());

這意味著媒體被髮布為端到端的流。由於 Cirrus 不能中轉媒體,你只能釋出為端到端的流。這個流包括了本地預設裝置的音訊和視訊,你可以通過 Settings Manager 選擇預設的裝置。

注意:直到有 FlashPlayer 同意接收媒體流,音訊 / 視訊才會被髮送。

現在,建立接收流:

private var recvStream:NetStream;

recvStream = new NetStream(netConnection, id_of_publishing_client);

recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamHandler); recvStream.play("media");

這時候,你將聽到聲音,你也能建立一個 Video 物件來顯示視訊。為了建立接收 NetStream ,你必需知道釋出者的 256 peer ID 。為了接收音訊 / 視訊,你必需知道釋出的流的名稱。

Advanced topics

釋出者可在終端之上精細控制哪些可以接收他釋出的流。當一個使用者試圖去接收一個分發流時,在釋出 NetStream 上的 onPeerConnect( ) 方法被呼叫(預設返回 true )。釋出者可以駁回某些 Flash Player 終端接收媒體的請求。

var o:Object = new Object();

o.onPeerConnect = function(subscriberStream:NetStream):Boolean

{

if (accept) {

return true;

}

else {

return false;

}

}

sendStream.client = o;

在釋出者方面, NetStream.peerStreams 屬性儲存著所有訂閱正在分發的 NetStream 的例項。例如,用 sendStream.send() 能傳送同一資料到所有訂閱者。你可以用下面的方法傳送資訊到指定訂閱者。

sendStream.peerStreams[i].send()

NetConnection.maxPeerConnections 屬性指定了允許連線到釋出者的對等流的數量 。其預設值為 8 ,但實際上,是取決於你的應用程式,你必須考慮到大多數 ISP 提供非對稱的網際網路接入服務。 1 說明了三個 Flash Player 例項 直接通訊。每個 Flash Player 的客戶端 傳送和接收兩個流,建立一個完全的連線網格。由於網際網路下載的能力普遍高於上傳的能力,你必須要格外小心,不要超終端使用者的上行負荷。

Figure 1. End-to-end connections using the Cirrus service

1 ,使用 Cirrus 服務的端到端連線

NetConnection.unconnectedPeerStreams 屬性是一個尚未與分發 NetStream 關聯的 NetStreams 的陣列。當一分發流與一個訂閱流名稱相同時,這個訂閱 NetStream 從這個陣列轉移到分發的 NetStream.peerStreams 陣列。

Exploring the Video Phone sample application

為了說明如何使用 Flash Player 10 的端到端功能,我們已經開發了一個 Video Phone 應用示例。它也是這份文件的一部分。

Video Phone 靠一個簡單的 HTTP 服務交換 Flash Player peer ID 。該指令碼作為包的一部分。此 WEB 服務不提供任何的使用者身份認證。 Flash Player 在成功連線到 Cirrus 之後,註冊一個 peer ID 。當撥通一個電話時, Video Phone 呼叫者通過 web 服務查詢接受者的 ID

為了主辦這個 Video Phone 樣例, Adobe 專門執行這個 web 服務。在你建立自己的 Video Phone 樣例時,你必須執行你自己的 web 服務,並在 VideoPhonLabs.mxml 中指定 WebServiceUrl 。你應該重寫 AbstractIdManger 類去實現你自己的 peer ID 交換機制。例如, XMPP 協議、 Google 應用服務或 Facebook 框架。

建立 Video Phone 應用樣例需要以下步驟:

  1. 使用提供的 reg.cgi Python 指令碼,執行用於交換 peer ID web 服務主機。
  2. Flash Builder 4 建立一個新 Flex 專案。
  3. 將包中的原始檔新增到專案中的 src 資料夾中。
  4. VideoPhoneLabs.mxml 中用 DeveloperKey 指定你的 Cirrus 開發者 key
  5. VideoPhoneLabs.mxml 檔案中用 WebServiceUrl 指定 web 服務的 URL

Video Phone 應用示例使用了電視模型。呼叫建立過程是通過使用端到端 NetStream.send() 的資訊。由於你只能在已建立的 NetStream 上使用 NetStream.send() 方法, Video Phone 釋出一個所謂的“ listener stream ”(用固定名稱)到其它能連線的 Flash Player 終端。當 A 使用者(呼叫者)想要與 B 使用者聯絡,他要訂閱 B 使用者的 listener stream 。這時候, B 使用者收到呼叫者的 peer ID (用 onPeerConnect() )並訂閱 A 使用者的媒體流。通過這個媒體流, A 使用者通知 B 使用者有關他的使用者友好的名字(用 NetStream.send() 方法),即使用者可以選擇接受或是拒絕呼叫。如果接受呼叫, B 使用者釋出媒體流,建立兩路通訊。