流媒體協議(二):RTMP協議

1、概念與摘要

RTMP協議從屬於應用層,被設計用來在適合的傳輸協議(如TCP)上覆用和打包多媒體傳輸流(如音頻、視頻和互動內容)。RTMP提供了一套全雙工的可靠的多路複用消息服務,相似於TCP協議[RFC0793],用來在一對結點之間並行傳輸帶時間戳的音頻流,視頻流,數據流。一般狀況下,不一樣類型的消息會被分配不一樣的優先級,當網絡傳輸能力受限時,優先級用來控制消息在網絡底層的排隊順序。服務器

2、RTMP塊流

實時消息傳遞協議塊流(RTMP塊流)。它做爲一款高級多媒體流協議提供了流的多路複用和打包服務。RTMP塊流被設計用來傳輸實時消息協議,它可使用任何協議來發送消息流。每一個消息都包含時間戳和有效類型標識。RTMP塊流和RTMP適用於各類視聽傳播的應用程序,包括一對一的,和一對多的視頻直播、點播服務、互動會議應用程序。網絡

當使用一個可靠的傳輸協議如TCP[RFC0793]時,RTMP塊流提供了一種能夠在多個流中,基於時間戳的端到端交付全部消息的方法。RTMP塊流不提供任何優先級或相似形式的控制,但可使用更高級別的協議來提供這樣的優先級。例如,一個視頻服務器能夠根據發送的時間或確認每一個消息的時間,來決定爲一個網絡差的用戶丟棄視頻信息,以確保音頻信息的及時接收。dom

RTMP塊流不只包含了本身的協議控制信息,同時也提供了一個更高級別的協議機制,用來嵌入用戶控制信息。加密

消息格式

消息格式能夠被分割成多個塊,用來在更高的協議中支持多路複用。在建立塊消息格式時,應該包含如下字段:設計

時間戳
消息的時間戳。這個字段佔用4字節。視頻

長度
消息的有效長度。若是消息頭不能被忽略,它應該包括長度。這個字段在塊頭中佔用3字節。blog

類型ID
各類類型的協議控制消息的ID。這些消息使用RTMP塊流協議和更高級別的協議來傳輸信息。全部其餘類型的ID能夠用在高級協議,這對於RTMP塊流來講,是不透明的。事實上,RTMP塊流中沒有要求使用這些值做爲類型;全部(無協議的)消息多是相同的類型,或者應用程序使用這個字段來區分多個鏈接,而不是類型。這個字段在塊頭中佔用1字節。文檔

消息流ID
消息流ID能夠是任意值。當同一個塊流被複用到不一樣的消息流中時,能夠經過消息流ID來區分它們。另外,對於RTMP塊流而言,這是一個不透明值。該字段佔用4字節,使用小端序。同步

握手

RTMP鏈接從握手開始。它包含三個固定大小的塊,不像其餘的協議,是由頭部大小可變的塊組成的。直播

客戶端(初始化鏈接的一端)和服務端發送一樣的三個塊。爲了方便描述,客戶端發送的三個塊命名爲C0,C1,C2;服務端發送的三個塊命名爲S0,S1,S2。  

握手序列

客戶端經過發送C0和C1消息來啓動握手過程。客戶端必須接收到S1消息,而後發送C2消息。客戶端必須接收到S2消息,而後發送其餘數據。

服務端必須接收到C0或者C1消息,而後發送S0和S1消息。服務端必須接收到C1消息,而後發送S2消息。服務端必須接收到C2消息,而後發送其餘數據。

C0和S0格式

C0和S0包由一個字節組成,下面是C0/S0包內的字段:

                              0 1 2 3 4 5 6 7
                             +-+-+-+-+-+-+-+-+
                             |   version     |
                             +-+-+-+-+-+-+-+-+
                              C0 and S0 bits

版本(8比特)
在C0包內,這個字段表明客戶端請求的RTMP版本號。在S0包內,這個字段表明服務端選擇的RTMP版本號。此文檔使用的版本是3。版本0-2用在早期的產品中,如今已經被棄用;版本4-31被預留用於後續產品;版本32-255(爲了區分RTMP協議和文本協議,文本協議一般以可打印字符開始)不容許使用。若是服務器沒法識別客戶端的版本號,應該回復版本3。客戶端能夠選擇下降到版本3,或者停止握手過程。

C1和S1格式

C1和S1包長度爲1536字節,包含如下字段:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        time (4 bytes)                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        zero (4 bytes)                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        random bytes                           |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         random bytes                          |
     |                            (cont)                             |
     |                             ....                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                              C1 and S1 bits

時間(4字節)
本字段包含一個時間戳,客戶端應該使用此字段來標識全部流塊的時刻。時間戳取值能夠爲零或其餘任意值。爲了同步多個塊流,客戶端可能但願多個塊流使用相同的時間戳。

零(4字節)
本字段必須爲零。

隨機數據(1528字節)
本字段能夠包含任意數據。因爲握手的雙方須要區分另外一端,此字段填充的數據必須足夠隨機(以防止與其餘握手端混淆)。不過不必爲此使用加密數據或動態數據。

C2和S2格式

C2和S2包長度爲1536字節,做爲C1和S1的迴應,包含如下字段:

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        time (4 bytes)                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                       time2 (4 bytes)                         |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                        random echo                            |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                         random echo                           |
     |                            (cont)                             |
     |                             ....                              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                              C2 and S2 bits

時間(4字節)
本字段必須包含對端發送的時間戳。

時間(4字節)
本字段必須包含時間戳,取值爲接收對端發送過來的握手包的時刻。

隨機數據(1528字節)
本字段必須包含對端發送過來的隨機數據。握手的雙方可使用時間1和時間2字段來估算網絡鏈接的帶寬和/或延遲,可是不必定有用。

3、RMTP握手

握手過程示意圖

+-------------+                           +-------------+
|    Client   |       TCP/IP Network      |    Server   |
+-------------+            |              +-------------+
      |                    |                     |
Uninitialized              |               Uninitialized
      |          C0        |                     |
      |------------------->|         C0          |
      |                    |-------------------->|
      |          C1        |                     |
      |------------------->|         S0          |
      |                    |<--------------------|
      |                    |         S1          |
 Version sent              |<--------------------|
      |          S0        |                     |
      |<-------------------|                     |
      |          S1        |                     |
      |<-------------------|                Version sent
      |                    |         C1          |
      |                    |-------------------->|
      |          C2        |                     |
      |------------------->|         S2          |
      |                    |<--------------------|
   Ack sent                |                  Ack Sent
      |          S2        |                     |
      |<-------------------|                     |
      |                    |         C2          |
      |                    |-------------------->|
 Handshake Done            |               Handshake Done
      |                    |                     |
          Pictorial Representation of Handshake
                     握手示意圖

下面是握手示意圖中提到的狀態:

未初始化
協議版本號在此階段發送。客戶端和服務器均處於未初始化狀態。客戶端發送攜帶協議版本號的C0包。若是服務器支持此版本,回覆S0和S1包。若是服務器不支持此版本,使用適當的動做回覆。在RTMP協議中,此動做是停止鏈接。
注: 在」C0和S0格式」章節中說起,若是服務器不支持客戶端的版本號,能夠選擇降到版本3或停止。

發送版本
客戶端和服務器雙方在未初始化狀態後,會進入發送版本狀態。以後,客戶端等待S1包,服務器等待C1包。待接收到數據包,客戶端發送C2包,服務器發送S2包。而後,雙方都進入答覆狀態。客戶端等待C2的答覆,服務器等待S2的答覆。

握手完成客戶端和服務器交換消息。

相關文章
相關標籤/搜索