原文: http://blog.csdn.net/defonds/article/details/17403225javascript
譯序:本文是維基百科關於 RTMP 的解釋, 關於 RTMP 官方規範參見 RTMP 規範,關於 RTMP 官方規範的中文版,參見《Adobe 官方公佈的 RTMP 規範》。如下是維基百科原文:php
實時消息傳輸協議(RTMP)最初是由 Macromedia 爲互聯網上 Flash player 和服務器之間傳輸音頻、視頻以及數據流而開發的一個私有協議。Adobe 收購 Macromedia 購之後,公佈了這個協議的一部分,以備公共使用。html
RTMP 協議有多個變種:
1. 工做在 TCP 協議之上,並使用默認端口號 1935 的明文協議。
2. RTMPS 使用 TLS/SSL 鏈接的 RTMP 協議。
3. RTMPE 使用 Adobe 本身的安全機制的加密 RTMP。雖然它的實現細節是私有的,但使用的是行業標準加密原語。RTMPE 的設計是有缺陷的,它自己並不提供實際的安全。
4. RTMPT 封裝在 HTTP 請求內部以穿越防火牆的協議。RTMPT 經常使用於創建 TCP 端口 80 和 443 的請求以繞開不少公司的流量過濾。封裝的會話中可能會攜帶純 RTMP、RTMPS 或者 RTMPE 包。java
儘管 RTMP 協議的本意是一個用於播放 Flash 視頻的協議,但它也每每用於其餘應用,好比 Adobe LiveCycle數據服務。linux
基本操做
RTMP(RTMFP 除外)是一個基於 TCP 的、持久鏈接並提供低延遲通訊的協議。爲了可以順利地傳輸流,而且傳遞儘量多的信息,RTMP 對流進行分段,客戶端和服務器能夠對分段長度進行協商,儘管有時分段長度是不變的:對於音頻數據默認分段長度是 64 字節,視頻數據和大部分其餘數據類型默認分段長度是爲 128 字節。來自不一樣流的段會被隔離,並對單一鏈接的段進行合成。對於比較長的數據塊,RTMP 會在每一段中攜帶一個單字節頭,因此開銷很小。然而,事實應用中,不一樣的段並不互相交叉。交叉和合成是在數據包層完成的,RTMP 包穿過不一樣的活躍通道進行交叉,用這種方法來保證每一個通道都知足各自的帶寬、延遲以及其餘一些服務質量的需求。這種模型下交叉的 RTMP 包被視爲不可分割的,而且在分段級別是不交叉的。
RTMP 定義了一些虛擬通道,經過它們能夠發送和接收 RTMP 包,而且這些通道彼此是獨立運做的。例如,可能會有一個用於處理 RPC 請求和響應的通道,一個用於視頻流數據的通道,一個用於音頻流數據的通道,一個用於帶外控制信息(分段長度協商,等等)的通道,等等。在一個典型的 RTMP 會話中,在任意給定時間內,可能會有幾個通道是同時活躍的。當 RTMP 數據被編碼時,會產生一個包頭。包頭定義了其餘一些事項,要發送到通道的 id,這一包產生時的 timestamp (若是須要的話),以及這一包的有效負載。包頭後緊跟這一包實際負載的內容,包的內容是在發送給鏈接前根據當前協商好的分段長度分割好的。包頭本身不會分段,而且包頭的長度也不會被計入這一包第一個分段的長度中去。換句話說,分段的主題僅僅是 RTMP 的包負載(音頻數據)。
更高一層講,RTMP 壓縮 MP3 或者 AAC 音頻和 FLV1 視頻多媒體流,並使用 AMF (Action Message Format) 協議進行遠程方法調用 (RPCs)。所需的 RPC 服務都是異步的,它們使用單一的 client/server request/response 模型,所以不須要實時通訊。
加密
RTMP 會話可使用如下兩種方法的任意一種進行加密:
使用行業標準 TLS/SSL 機制。底層的 RTMP 會話唄簡單地封裝在一個普通的 TLS/SSL 會話中。
使用 RTMPE,將 RTMP 會話封裝在一個輕量級的加密層裏。
廣泛認爲,會話開始時的 TLS/SSL 握手是很是計算密集型的。Adobe 開發了 RTMPE 做爲一個輕量級的替代,給提供加密服務的高流量的站點一個實用的選擇。Adobe 通告 RTMPE 做爲一個安全內容傳遞的方法,以免模擬客戶端的操做,這種說法是錯誤的。RTMPE 僅使用了 Diffie-Hellman 機制,沒有提供任何一方的身份驗證,這很容易在會話初始化時受到中間人攻擊。
HTTP 隧道
在 RTMP 隧道 (RTMPT) 中,RTMP 數據被密封起來並經過 HTTP 進行交換,來自客戶端(在這種狀況下客戶端是爲 media player)的信息發送給服務器上的端口 80 (HTTP 默認端口號)。
因爲 HTTP 頭的緣故,RTMPT 中的信息要比等效的非通道的 RTMP 信息大,在非通道 RTMP 不能夠的場景中,好比當客戶端處於一個阻止非 HTTP 和 非 HTTPS 網絡流通時,RTMPT 能夠便利地使用。
這個協議經過使用 POST url 發送命令和使用 POST 體發送 AMF 消息進行工做。例子:web
用於打開一個鏈接。數組
規範文檔
Adobe 公開聲明的規範是 2009 年 6 月 15 日發佈的 RTMP specification。那個規範,忽略了(應該說沒有公開) 協議實現的關鍵細節。很難單單根據發佈的規範將 RTMP 協議整合進咱們的程序裏,太多必不可少的細節被忽略了,咱們只可以經過學習實現了這個協議的應用 (好比 librtmp),以及根據測試 TCP/IP 數據包捕獲,來判定其不多的細節。
Adobe 關於使用這一協議的 license 要求 RTMP 服務器的實現知足這一規範。
Adobe 發佈的規範中缺乏的細節包括:瀏覽器
數據包格式緩存
數據包由客戶端和服務器之間創建的 TCP 鏈接進行發送。數據包包含一個頭和一個體,至於鏈接和控制命令使用 AMF(Action Message Format)編碼。頭分爲基本報頭(在圖中顯示爲分離出來的那塊)和塊消息報頭。基本報頭是數據包惟一不變的部分,經常由一個複合字節組成,兩個有效位表明塊類型(規範中的格式),其他的組成了流 id。根據前者的值,一些消息頭字段能夠被忽略掉,這些字段由前面的數據包根據後面的值派生出來,基本報頭可使用兩個額外字節進行擴展(圖中的狀況總共有三個字節)。塊消息報頭包含 meta-data 信息,好比消息大小(以字節爲單位),Timestamp 以及消息類型。最後一個值是一個單獨的字節,它定義了這個包是一個音頻包,或者視頻包,或者命令以及 "低層次" RTMP 包好比一個 RTMP Ping。安全
如下示例,一個 flash 客戶端執行如下代碼時:
這將生成如下塊:
Hex Code | ASCII |
03 00 0b 68 00 00 19 14 00 00 00 00 02 00 0C 63 72 65 61 74 65 53 74 72 65 61 6D 00 40 00 00 00 00 00 00 00 05 | . . @ I . . . . . . . . . . . . c r e a t e S t r e a m . @ . . . . . . . . |
這一包以一個字節的基本報頭開始,兩個有效位(b00000011) 定義了塊頭類型 0,其他部分(b00000011) 定義了塊的流 ID 是 3。頭類型會有 4 種可能的值,他們的意義分別是:
最後一個類型 (b11) 經常使用於聚合信息的狀況,在上面的例子中,第二個消息會以 id 爲 0xC3 (b11000011) 起始,意味着全部消息報頭字段要以流 ID 爲 3 的消息傳遞(偏偏是其上的消息)。六個最低的有效位組成流 ID,取值範圍是 3 到 65599。一些值具備特殊意義,好比 1 表明一個擴展的 ID 格式,這時會有兩個字節跟隨。值爲 2 用於底層的消息,例如 Ping 和設置客戶端帶寬。
接下來的 RTMP 報頭的字節(包含以上數據包例子中的值)詳解以下:
消息類型 ID 字節定義了當前包是否包含音頻/視頻數據,一個遠程對象或者一個命令。一些可能的值以下:
緊跟報頭,0x02 表示一個大小爲 0x000C 的串,0x63 0x72 ... 0x6D ("createStream" 命令)。其後是 0X00 表明 ID 爲 2.0 的事務。最後一個字節是 0x05 (null) 表示沒有參數。
Invoke 消息結構 (0x14, 0x11)
以上所述的幾種消息類型,好比 Ping 和設置客戶端/服務端帶寬,被認爲底層 RTMP 協議消息,它們不使用 AMF 編碼格式。換句話說,命令消息,不管是 AMF0 (Message Type of 0x14) 仍是 AMF3 (0x11),使用這種格式:
事務 id 用於有回覆的命令。這個值能夠是上面例子中的一個字符串,也能夠是一個或者多個對象,每一個由一個鍵值對組成,鍵值對的鍵常常編碼爲字符串值,鍵值對的值能夠是任意 AMF 數字類型,包括複雜的類型,好比數組。
Ping 消息結構 (0x04)
Ping 消息不是 AMF 編碼。它們以一個流 Id 起始,帶有一個完整 (類型 0) 報頭,並有一個類型爲 0x04 的消息。報頭後面緊隨六個字節:
消息體的前兩個字節定義了 Ping 的類型,有六種可能取到的值。
Pong 是 Ping 回覆的名字,它使用以上介紹的值。
ServerBw/ClientBw 消息結構 (0x05, 0x06)
這個關聯到和客戶端向上流、服務器向下流比特率相關的消息。消息體由 4 個字節組成,表示帶寬的值,它可能有一個擴展字節來設置 Limit 類型。這個能夠有三種可能的值:hard、soft 或者 dynamic (就是 soft 或者 hard 任一)。
設置塊大小 (0x01)
這個值能夠在報體的四個字節裏接收到。存在默認值 128 字節,當你想要改變默認值時纔會發生這個消息。
協議
握手
創建 TCP 鏈接後,RTMP 鏈接會在兩端交互三個包的握手以後創建(這在官方文檔裏也被引用爲塊)。在官方規範中,這裏描述爲客戶端發送包 C0-2,服務器端發送包 S0-2,不要和 RTMP 包混淆,RTMP 包只會在握手完成以後才能交互。這些包擁有本身的結構,C1 包含一個設置 "epoch" timestamp 的字段,可是由於這個能夠設置爲 0,正如第三方實現過的,這個包能夠被簡化。客戶端經過發送一個帶有表明現有協議版本號常數值 0x03 的 C0 包初始化鏈接。它能夠直接跟隨 C1 而無須等待接收到 S0,它帶有 1536 字節,前四個字節表明 timestamp,其餘的隨意 (第三方實現中能夠將其設置爲 0)。C2 和 S2 分別是 S1 和 C1 的回聲,接收到它們以後,握手才被認爲結束。
鏈接
這一點上,客戶端和服務器會經過交互 AMF 編碼的消息進行協商鏈接。這些包含關係到創建鏈接所須要的變量的鍵值對。一個來自客戶端的消息例子以下:
FMS 和其餘市縣使用一個 "app" 的概念來概念化爲音頻/視頻和其餘內容定義一個容器,具體實現是,在服務根目錄下的一個文件夾,其下含有將要被流化的媒體文件。第一個變量含有這一 app 的名 "sample",這個是由 Wowza 服務器用於測試所提供的名字。flashVer 字符串和 Action-script 的 getversion() 方法返回的值同樣。audioCodec 和 videoCodec 使用 double 編碼,它們的含義能夠在原始規範裏找到。videoFunction 的值是 true,在這裏明顯是 SUPPORT_VID_CLIENT_SEEK 變量。特別有趣的是 objectEncoding,它定義了通訊的其他部分是否會使用擴展的 AMF3 格式。由於當前默認版本爲 3,flash 客戶端必須被以 Action-script 代碼顯式告知去使用 AMF0。服務器會用 ServerBW 回覆,一個 ClientBW 和一個 SetPacketSize 消息序列,最終跟隨一個 Invoke,用一個實例消息。
上面的一些值會被連續加載到一個通用的 Action-script Object,這個對象隨後被傳遞給 NetConnection 事件監聽者。clientId 將會爲這個鏈接開啓的會話創建一個編號。Object 編碼必須匹配前面設定的值。
播放視頻
要開始一個視頻流,客戶端發送一個由一個 ping 消息跟隨的 "createStream" 調用,其後再跟隨一個以文件名爲參數的 "play" 調用。服務器隨後以一系列的 "onStatus" 命令和帶有視頻數據的 RTMP 消息進行回覆。
鏈接創建之後,媒體由封裝爲 FLV tag 內容的 RTMP 消息對類型 8 和 類型 9 的音頻和視頻交疊發送。
HTTP 隧道 (RTMPT)
這一節講解 RTMP 的 HTTP 隧道式版本。它交互在端口 80,並在 HTTP POST 請求和回覆內部傳遞 AMF 數據。鏈接的時序以下:
第一個請求有一個路徑 /fcs/ident2,正確的返回是 404 沒法查找錯誤。客戶端而後發送了一個 /open/1 請求,服務器以附加一個表明 session 標識的隨機數的 200 ok 返回。在以上例子中,返回體中返回 1728724019。
今後開始,/idle/<session id>/<sequence #> 會輪詢請求,session id 是由服務器生成並返回,sequence 是一個爲以 1 開始之後每次請求遞增的數字。正確的回覆是一個報體中帶有指示內部時間的整數,200 OK。AMF 數據經過 /send/<session id>/<sequence #> 發送。
軟件實現
客戶端軟件
最普遍採用的 RTMP 客戶端軟件是 Adobe Flash Player,它可以支持來自 RTMP 服務器的音視頻流的回放(當它被安裝爲一個 web 瀏覽器的插件時)。
只能部分支持 RTMP 的客戶端軟件寶庫開源的 media player XBMC,它提供了播放 RTMP (不包括 RTMPE) 流的初步支持。
開源的命令行工具 rtmpdump 用於回放或者將整個 RTMP 流 (包括 Adobe 用於加密的 RTMPE) 保存到磁盤。RTMPdump 能夠運行在 Linux、Android、Solaris、MacOSX 以及大部分其餘的 Unix 派生操做系統,固然也能夠運行在微軟 Windows。最初支持全部 32 位版本的 Windows 系統,包括 Windows 98,從版本 2.2 起,這款軟件只能泡在 Windows XP 或者更高版本的 Windows 系統之上(儘管早期版本保持功能齊全)。
RTMPdump 的一個分叉,沒有包含 Adobe 聲稱違反了美國 DMCA 的 RTMPdump 代碼,以 FLVstreamer 發佈了。它的開發是 2008 年 Adobe 抵制 RTMPdump 的一個直接反應。FLVstreamer 能夠未來自任意一臺 RTMP 服務器的音頻流或者視頻流保存到磁盤,只要流沒有開啓 RTMPE。FLVstreamer 運行於 Windows XP 或者更高版本的 Windows 系統之上,但不支持早期版本的 Windows。
2009 年十月,在美國之外的國家,MPlayer 網站 從新啓動了 RTMPdump 的研發。現有版本大大改進了功能,而且使用了 C 語言重寫,大大利用了 C 的優點。尤爲是,主要功能被內置到一個庫 (librtmp) 中,其餘程序能夠很容易使用這些功能。RTMPdump 的開發者們也爲其餘一些開源項目 (諸如 MPlayer、FFmpeg、XBMC、cURL、VLC) 提供了 librtmp 的支持。這些項目對 librtmp 的使用,擁有了徹底 RTMP 的支持。
開源的 Gnash,一個在 Linux 平臺上對於 Macromedia Flash Player 的替代,擬就爲 Linux 支持 RTMP streaming。
服務器端軟件
一些全面執行 RTMP 的服務器有:
探索和研發
另請參閱
參考資料
外部連接
原文連接:http://en.wikipedia.org/wiki/Real_Time_Messaging_Protocol。