RTMP協議

RTMP協議

  Real Time Messaging Protocol(實時消息傳送協議協議)概述
  實時消息傳送協議是Adobe Systems公司爲 Flash播放器和服務器之間音頻、視頻和數據傳輸開發的私有協議。它有三種變種:
  1)工做在 TCP之上的明文協議,使用端口 1935
  2)RTMP T封裝在 HTTP請求之中,可穿越防火牆;
  3)RTMP S相似RTMPT, 但使用的是HTTPS鏈接;
  介紹:
  RTMP協議是被Flash用於對象,視頻,音頻的傳輸.該協議創建在TCP協議或者輪詢HTTP協議之上.
  RTMP協議就像一個用來裝數據包的容器,這些數據 能夠是AMF格式的數據,也能夠是FLV中的視/音頻數據.
  一個單一的鏈接能夠經過不一樣的通道傳輸多路網絡流.這些通道中的包都是按照 固定大小的包傳輸的.
  網絡鏈接(Connection)
  一個Actionscript鏈接並播放一個流的簡單代碼:
  
複製代碼
代碼
  var videoInstance:Video  =  your_video_instance;
  var nc:NetConnection 
=   new  NetConnection();
  var connected:Boolean 
=  nc.connect( " rtmp:/localhost/myapp " );
  var ns:NetStream 
=   new  NetStream(nc);
  videoInstance.attachVideo(ns);
  ns.play(
" flvName " );
複製代碼

 

  默認端口爲1935
  握手
  Client → Server :向服務器發出握手請求. 這不屬於協議包一部分,該握手請求第一個字節爲(0×03),其後跟着1536個字節.經管看上去這部分的內容對於RTMP協議來講並非相當重要的,但也不可隨意對待.
  Server → Client :服務器向客戶端迴應握手請求.這部分的數據仍然不屬於RTMP協議的部分.該回應的其實字節仍然爲(0x03),可是後邊跟着個長度爲1536個字節 (一共爲3072 )的包塊.第一個1536塊看上去彷佛能夠是任意內容,甚至好像能夠是Null都沒有關係.第二個1536的代碼塊,是上一步客戶端向服務器端發送的握手 請求的內容.
  Client→Server:把上一步服務器向客戶端迴應的第二塊1536個字節的數據塊.
  至此客戶端與服務器端的握手結束,下面將發送RTMP協議的包內容.
  Client → Server :向服務器發送鏈接包.
  Server → Client :服務器迴應.
  ... .... 等等... ...
  RTMP 數據類型
  0×01 Chunk Size changes the chunk size for packets
  0×02 Unknown anyone know this one?
  0×03 Bytes Read send every x bytes read by both sides
  0×04 Ping ping is a stream control message, has subtypes
  0×05 Server BW the servers downstream bw
  0×06 Client BW the clients upstream bw
  0×07 Unknown anyone know this one?
  0×08 Audio Data packet containing audio
  0×09 Video Data packet containing video data
  0x0A - 0×11 Unknown anyone know?
  0×12 Notify an invoke which does not expect a reply
  0×13 Shared Object has subtypes
  0×14 Invoke like remoting call, used for stream actions too.
  Shared Object 數據類型
  0×01 Connect
  0×02 Disconnect
  0×03 Set Attribute
  0×04 Update Data
  0×05 Update Attribute
  0×06 Send Message
  0×07 Status
  0×08 Clear Data
  0×09 Delete Data
  0x0A Delete Attribute
  0x0B
  Initial Data
  RTM P包結構
  RTMP包 包含一個固定長度的包頭和一個最長爲128字節的包體.包頭能夠是下面4種長度的任意一種:12, 8, 4, or 1 byte(s).
  第一個字節的前兩個Bit很重要,它決定了包頭的長度.它能夠用掩碼0xC0進行"與"計算.下面的表格羅列了可能的包頭長度:Bits Header Length
  00 12 bytes
  01 8 bytes
  10 4 bytes
  11 1 byte
  咱們在這裏討論關RTMP包結構的問題並非很是的詳細.咱們在之後有時間會討論關於AMF的問題(敬請期待...:loveliness:),其實RTMP包結構就是使用了AMF格式.
  流
  關於流的操做咱們須要進一步研究,在論壇中的http://www.openred5.com /bbs/viewthread.php?tid=175&extra=page%3D1這篇文章研究的仍是不錯的,你們能夠參考.不過下面能夠 列一個關於客戶端向服務器端發送流的流程:
  Client→Server :發送一個建立流的請求.
  Server→Client :返回一個表示流的索引號.
  Client→Server :開始發送.

  Client→Server :發送視音頻數據包(這些包在同一個頻道(channel)並用流的索引號來惟一標識). php

 

 

 一、協議研究概述
   協議設計和分析一直都是在工做遇到,正好在這裏總結一下,說到協議,在這個網絡的時代,沒有人能夠離開它了。他存在咱們生活中的任何角落,只不過咱們平 時,並無注意到它的存在,能夠這麼說若是沒有協議,咱們生活和平常的工做生產都不能進行。若是仔細想一想你生活中用到的全部東西,協議已經包含其中。那到 底什麼是協議呢?說的簡單一點就是雙方達成的共識,以便更好的交流,理論上協議是什麼呢?若是學過《信號與系統》的人都知道有個簡單的道理,就是信息在經 過一個管道的符號集,到另外一個符號集時信息不會丟失。 html

    任何複雜的事物都有個最簡單的本質,網絡上的協議也是這樣,有個最基本的本質。除去上下層的概念,協議就只剩下通訊雙方實體的規則。 算法

   通常的協議都包含最基本的協議頭,不論是物理層、鏈路層、仍是網絡層,這個頭就構成了協議的本質東西。一般協議頭要包含如下最基本的三項信息: 數組

    1> 雙方實體的惟一標示,用來標示通訊雙方的實體。
    2> 類型描述或者是淨核描述,標誌淨核的內容。
    3> 協議淨核的長度,用來在萃取淨核的內容應用。
   其中,前兩項是必需要有的,沒有他們,通訊雙方的交互根本得不到保證,第三項在不太靈活的通訊中能夠去掉,而有第二項的類型推出。 瀏覽器

    協議的豐富性,有淨核的多樣性體現。 服務器

   協議頭除了以上的三項,還能夠增長更多的信息(好比控制信息、時間信息等),取決於具體的應用。找到這些基本的東西,再去看協議的時候,可以更好的抓住協議的主體進行分析和設計了。 網絡

2 RTMP 協議概述
   RTMP 協議是被 Flash 用於對象、視頻、音頻的傳輸。該協議創建在 TCP 協議或者輪詢 HTTP 協議之上, RTMP 協議就像一個用來裝數據包的容器,這些數據能夠是 AMF 格式的數據,也能夠是 FLV 中的視 / 音頻數據。一個單一的鏈接能夠經過不一樣的通道傳輸多路網絡流,這些通道中的包都是按照固定大小的包傳輸的 . app

3 RTMP 協議部分
3.1 協議頭 ide

 

複製代碼
代碼
struct  RTMP_HEAD 



      
char  cChannelid :  6 ; //  第一個字節的後 6 位 

      
char  cCheadsize ;  //  第一個字節的頭兩位 

      
char  cTimer[ 3 ];   //  三個字節表示的時間信息 

      
char  cLength[ 3 ];  //  三個字節表示的長度 

      
char  cDatatype;  //  數據類型 

      
char  sStreamid[ 4 ];  //  流標識 

}; 
複製代碼

 

  這裏有三個最基本的元素(惟一標示 )、(類型 )和(淨核的長度 )分別是: cChannelid 、 cDatatype 和 cLength 。 ui

3.2 數據類型
  數據類型 決定了協議上層能夠作的具體的事情,和使用協議的人必須遵循的規則。

  同時數據類型 說明了淨核 的基本內容。

  RTMP 數據類型:

0×01  Chunk Size  changes the chunk size for packets 
0×02  Unknown  anyone know this one? 
0×03  Bytes Read  send every x bytes read by both sides 
0×04  Ping  ping is a stream control message, has subtypes 
0×05  Server BW  the servers downstream bw 
0×06  Client BW  the clients upstream bw 
0×07  Unknown  anyone know this one? 
0×08  Audio Data  packet containing audio 
0×09  Video Data  packet containing video data 
0x0A - 0×11  Unknown  anyone know? 
0×12  Notify  an invoke which does not expect a reply 
0×13  Shared Object  has subtypes 
0×14  Invoke  like remoting call, used for stream actions too. 

3.3 協議的淨核
   RTMP 的協議淨核是用 AMF 格式來 描述, AMF 格式自己的產生就是爲了 RTMP 協議服務的,最初的 RTMP 採用 XML 的形式傳輸數據,但 XML 只是字符形式的值對的格式傳輸數據,而隨着應用的普及這徹底不能知足要求了,好比對象、結構、數組,甚至能夠是數據集,配合 DataGrid 組件能夠很方便地顯示數據。
爲了處理複雜數據類型,採用一種獨有的方式使 Flash 與應用服務器間能夠來回傳送數據勢在必行。因而 AMF 應運而生。

  AMF 是 Adobe 獨家開發出來的通訊協議,它採用二進制壓縮,序列化、反序列化、傳輸數據,從而爲 Flash 播放器與 Flash Remoting 網關通訊提供了一種輕量級的、高效能的通訊方式。 
 
 AMF 最大的特點在於可直接將 Flash 內置對象,例如 Object, Array, Date, XML ,傳回服務器端,而且在服務器端自動進行解析成適當的對象,這就減輕了開發人員繁複工做,同時也更省了開發時間。因爲 AMF 採用二進制編碼,這種方式能夠高度壓縮數據,所以很是適合用 來傳遞大量的資料。數據量越大, Flash Remoting 的傳輸效能就越高,遠遠超過 Web Service 。至於 XML, LoadVars 和 loadVariables() ,它們使用純文本的傳輸方式,效能就更不能與 Flash Remoting 相提並論了。
   注意: Flash Remoting 須要瀏覽器支持 Binary POST , Flash 播放器在 Netscape 6.x. 環境下運行 Flash Remoting 會不起做用( Flash Remoting 調用沒有效果也不返回錯誤), Netscape 7 已經糾正了這個 bug 。對於早期 Safari 和 Chimera 版的蘋果機也有這個問題。
  一樣是輕量級數據交換協議,一樣是經過調用遠程服務,一樣是基於標準的 HTTP 和 HTTPS 協議, Flash Remoting 爲何選擇了使用 AMF 而放棄了 SOAP 與 Flash 播放器通訊呢  有以下緣由:
 
SOAP 將數據處理成 XML 格式,相對於二進制的 AFM 太冗長了; 
AMF 能更有效序列化數據;由於 AMF 的初衷只是爲了支持 Flash ActionScript 的數據類型,而 SOAP 卻致力於提供更普遍的用途; 
AMF 支持 Flash 播放器 6 只須要瀏覽器增長 4 KB 左右(壓縮後)的大小,而 SOAP 就大多了; 
SOAP 的一些頭部文件請求在 Flash 播放器 6 不支持。那 Flash 播放器 6 爲何能訪問基於 SOAP 的 Web 服務呢?原來 Flash Remoting 網關將 SOAP 請求在服務器端與轉換成 AFM 格式,而後利用 AFM 與 Flash 播放器通訊。另外, AMF 包中包含 onResult 事件(好比說 response 事件)和 onStatus 事件(好比說 error 事件),這些事件對象在 Flash 中能夠直接使用。 
AMF 從 Flash MX 時代的 AMF0 發展到如今的 AMF3 。 AMF3 用做 Flash Playe 9 的 ActionScript 3.0 的默認序列化格式,而 AMF0 則用做舊版的 ActionScript 1.0 和 2.0 的序列化格式。 在網絡傳輸數據方面, AMF3 比 AMF0 更有效率。 AMF3 能將 int 和 uint 對象做爲整數( integer )傳輸,而且能序列化 ActionScript 3.0 才支持的數據類型 , 好比 ByteArray , XML 和 Iexternalizable 。

      AMF 很好的解決了內容的豐富性。(具體 AMF 格式參考附件格式文檔)

3.3.1 AMF中的數據類型Data Types
AMF0 supports the following data types (with their type field values):

NUMBER = 0x00
BOOLEAN = 0x01
STRING = 0x02
OBJECT = 0x03
MOVIECLIP = 0x04
NULL_VALUE = 0x05
UNDEFINED = 0x06
REFERENCE = 0x07
ECMA_ARRAY = 0x08
OBJECT_END = 0x09
STRICT_ARRAY = 0x0a
DATE = 0x0b
LONG_STRING = 0x0c
UNSUPPORTED = 0x0d
RECORD_SET = 0x0e
XML_OBJECT = 0x0f
TYPED_OBJECT = 0x10
Binary Format
AMF format for a value/object consists of a type byte (see above) followed by zero or more bytes. This section describes the bytes following the type byte for various types.

NUMBER (type byte: 0x00)
Numbers are stored as 8 byte (big endian) float double. On x86 you can just byteswap a double to encode it correctly.

BOOLEAN (type byte: 0x01)
A boolean is encoded in one byte. FIXME: is true sent as 0xff? 0x01?

STRING (type byte: 0x02)
A string is encoded as a 2 byte (big endian) count (number of bytes) followed by that many bytes of text. Note: there is no null terminator.

I think the text is assumed to be UTF-8. Can someone double check me on this?

NULL_VALUE (type byte: 0x05)
A null has zero bytes following the type byte

UNDEFINED (type byte: 0x06)
A undefined has zero bytes following the type byte

OBJECT (type byte: 0x08)
An object is encoded as a series of key/value pairs. The key is encoded as a STRING (above) WITH NO TYPE BYTE, and the value is any AMF value.

The object encoding is terminated by 0x000009 (that is a zero length string key, followed by the OBJECT_END type byte described below.

OBJECT_END (type byte: 0x09)
This is not really a value, but a marker for the end of an OBJECT. See above.

STRICT_ARRAY (type byte: 0x0a)
This is the encoding for arrays such as ["foo", "bar", 1, 2, 3]. For a hash (a set of key/value pairs) you'll need to use OBJECT above.

An array is encoded as 4 byte (big endian) integer which is the number of elements in the array, followed by that many AMF values.

That's it. There's no terminator of any kind.

Use in shared object files
While most AMF objects are just a value, there is a special variation used by shared object files for properties. Rather than start with the type field, followed by the length, it starts with a byte count, then the name, and then the regular AMF type field, the length, and then the data.

3.4 客戶端和服務器的鏈接過程
3.4.1客戶和服務器的握手
 

   Flash Player 以系統時間做爲種子經過某種算法生成的數字簽名,大小是 1537 字節向服務器發起第一次握手,服務器根據客戶端的數字簽名產生一個 3073 字節的驗證包,給客戶端,客戶端在接受到服務器的迴應之後會發送一個 1536 字節的回覆。

具體的流程:

發送第一次握手包 handshark1
接收第二次握手包 handshark2
發送的三次握手包 handshark3
第 一個握手包 handshark1 和服務器的回覆握手包 handshark2 都是以 0X03 開頭。這三次握手不是 RTMP 協議自己的內容,因此在這並無包含 RTMP  的協議頭。是服務器的廠家本身產品作驗證用的,嚴格的說就是你必須用  Adobe 的客戶端和服務器才能使用個人協議。

3.4.2客戶和服務器通訊
   具體鏈接和請求視頻的過程

發送 rtmp_connect 命令
. 發送本地帶寬消息 . 默認是 125000
服務器返回服務器帶寬信息
服務器返回本地帶寬信息
服務器返回鏈接成功消息 "NetConnection.Connect.Success"
客戶端發送建立流請求 encodeCreateStreamPacket
服務器返回建立流成功消息
客戶端發送播放文件消息 Rtmp_Play
服務器返回 TYPE_CHUNK_SIZE 消息
服務器返回開始播放消息 "NetStream.Play.Start"
服務器返回視頻信息 (TYPE_STREAM_METADATA) ,包括大小,寬高,速率等等信息--文件長度能夠在這裏推算出來
RTMP 的淨核決定了內容服務, adobe 的服務器採用的 AMF 格式的字串命令來控制視頻的傳輸和播放,具體的字串命令信息以下:(注:字串的定義有廠家( adobe )本身定義,只要知足 AMF 的格式就能夠)
NetConnection.Call.Failed
NetConnection.Call.BadVersion 
NetConnection.Connect.AppShutdown
NetConnection.Connect.Closed
NetConnection.Connect.Rejected
NetConnection.Connect.Success
NetStream.Clear.Success
NetStream.Clear.Failed
NetStream.Publish.Start
NetStream.Publish.BadName
NetStream.Failed
NetStream.Unpublish.Success
NetStream.Record.Start
NetStream.Record.NoAccess
NetStream.Record.Stop
NetStream.Record.Failed
NetStream.Play.InsufficientBW
NetStream.Play.Start
NetStream.Play.StreamNotFound
NetStream.Play.Stop
NetStream.Play.Failed
NetStream.Play.Reset
NetStream.Play.PublishNotify
NetStream.Play.UnpublishNotify
NetStream.Data.Start
Application.Script.Error
Application.Script.Warning
Application.Resource.LowMemory
Application.Shutdown
Application.GC
Play
Pause
demoService.getListOfAvailableFLVs
getStreamLength
connect
app
flashVer
swfUrl
tcUrl
fpad
capabilities
audioCodecs
audioCodecs
videoCodecs
videoFunction
pageUrl
createStream
deleteStream
duration
framerate
audiocodecid
audiodatarate
videocodecid
videodatarate
height
width
3.4.2數據的萃取
      在服務器返回開始播放消息 "NetStream.Play.Start" 以後,服務器就會開始給客戶端傳輸數據了,通常數據的萃取都是先解析協議的頭,而後根據協議頭中數據類型和淨核長度就能夠把數據部分取出, RTMP 協議也是這樣。

 

複製代碼
代碼
struct  RTMP_HEAD 



      
char  cChannelid :  6 ; //  第一個字節的後 6 位 

      
char  cCheadsize ;  //  第一個字節的頭兩位 

      
char  cTimer[ 3 ];   //  三個字節表示的時間信息 

      
char  cLength[ 3 ];  //  三個字節表示的長度 

      
char  cDatatype;  //  數據類型 

      
char  sStreamid[ 4 ];  //  流標識 


複製代碼

 

 

      首先判斷 cDatatype 是那種類型,而後根據不一樣的類型進行萃取數據部分,進行不一樣的處理,獲取視頻的數據的方式先看是不是一下的類型:

0×08  Audio Data  packet containing audio 
0×09  Video Data  packet containing video data 

  根據淨核的長度讀取出內存中的音視頻數據,這裏的音視頻數據是有必定編碼格式的數據,這個取決於應用的具體配置, Flash play 使用的是 FLV 的格式。要對這部分數據進行存取,還有作一部分工做,對 FLV 的視頻數據進行去殼,取出數據保存文件就能夠了。

相關文章
相關標籤/搜索