前端須要瞭解的RTMP知識

前端須要瞭解的RTMP知識

概述

RTMP是Real Time Messaging Protocol的簡稱,是基於什麼時候的傳輸層協議上(如tcp協議)的應用層級別的協議,其設計是爲了組包多媒體傳輸流(如視頻,音頻以及交互內容)前端

介紹

RTMP協議是由Adobe公司提出的一種應用層的協議,上面引述的是RTMP官方文檔的introduction部分,其目的是爲了給諸如視頻、音頻以及數據消息通訊雙方提供實時的信息雙向流。RTMP在實現上對不一樣類型的消息實施不一樣的權重,這樣能夠實現對當傳輸量受限時的底層流傳輸消息進行排隊。git

定義

  • 載荷(Payload):包含在包中的數據
  • 包(Packet):數據包由固定頭和載荷數據組成,一些底層協議可能須要對被定義包進行封裝
  • 端口(Port):TCP/IP端口,由主機號來區分多地址
  • 傳輸地址(Transport address):網絡地址和端口的組合
  • 消息流(Message stream):消息流通訊的邏輯頻道
  • 消息流ID(Message stream ID):每一個消息都有一個預期消息流匹配的id
  • 塊(Chunk):消息片斷。消息在被網絡傳輸前會被分紅小的部分,全部的消息會經過多路由時間序端對端傳輸
  • 塊流(Chunk stream):通訊的邏輯頻道容許塊以某一特定方向傳送,塊流能夠從客戶端傳到服務端,也能夠從服務端傳回客戶端
  • 塊流ID(Chunk stream ID):每一個塊流都有一個與之匹配的id
  • 多路複用(Multiplexing):分離的音視頻數據能夠連續播放的過程,使得音視頻能夠同時傳送
  • 多路分用(DeMultiplexing):多路複用的逆過程,能夠將交錯的音視頻數據彙集成原始的音視頻數據
  • 遠程過程調用(Remote Procedure Call):容許客戶端或服務端能夠調用另外一端服務端或客戶端子程序或子進程的請求
  • 元數據(Metadata):數據的描述。電影的元數據包括電影標題,時長,上映日期等等。
  • 應用實例(Application Instance):客戶端能夠鏈接併發送鏈接請求的服務端實例
  • 動做消息格式(Action Message Format):用來序列化AS(ActionScript 動做腳本)實例對象(object graphs)的壓縮的二進制格式,有AMF0和AMF3兩種版本

字節序 & 對齊 & 時間格式

全部的整字段以字節序來傳輸,而且是大端排列,不作特殊說明均爲十進制。時間戳以毫秒記,從0開始,32位長;時間間隔用毫秒的無符號整數表示,多是24或32位長度github

RTMP塊流

儘管RTMP是被設計用來實時傳輸消息的,但它也能夠用來處理任何消息。RTMP很是適合用於大量的音視頻應用,雖然並不會提供任何優化,但卻被用於更高級別的協議來進行優化,例如直播視頻服務器可能會選擇在客戶端網速較慢的狀況下丟棄視頻消息而保證音頻消息的實時到達。web

消息格式

消息格式可被分紅許多塊來提供多路複用,這些消息須要包括含如下字段:segmentfault

字段名 含義 大小
時間戳(Timestamp) 消息的時間戳 4字節
長度(Length) 消息載荷的長度,若是消息頭不能被省略,須要包含長度 3字節
類型ID(Type ID) 類型id被用於消息控制 1字節
消息流ID(Message Stream ID) 任意數值,小端存儲 4字節

握手

RTMP握手不一樣於其餘協議,它包含3個固定大小的塊而不是可變大小的塊服務器

握手次序

開始時,客戶端發送C0和C1網絡

客戶端必須在收到S1才能發送C2,收到S2才能發送任何其餘數據併發

服務端必須等到收到C0才能發送S0和S1,而且最好能在收到C1後。服務端等到收到C1才能發送S2,服務端必須等到收到C2才能發送其餘數據dom

C0 & S0 格式

C0和S0是一個8位組,被認爲是一個8位整數段。對C0而言,這個字段被認爲是客戶端RTMP請求的版本;對S0而言,這個字段被認爲是服務端選擇的RTMP版本。默認是3,0-2被廢棄,4-31被用於將來的版本,32-255沒有被容許tcp

0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|   version     |
+-+-+-+-+-+-+-+-+

C1 & S1 格式

C1和S1是一個1536位的長度組,包含以下字段:

字段名 含義 大小
時間(Time) 包含時間戳,多是0也多是任意的數值,用於時間標識 4字節
零(Zero) 必須都是0 4字節
任意數據(Random data) 任意數值,並不須要加密 1528字節
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)                            |
|                              ....                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

C2 & S2 格式

C2和S2是一個1536位的長度組,對應S1和C1依次的回覆,包含以下字段:

字段名 含義 大小
時間1(Time1) 時間戳,S1(C2發送)或C1(S2發送) 4字節
時間2(Time2) 時間戳,以前S1或C1 4字節
任意數據(Random data) 任意數值,可快速驗證鏈接帶寬或延時 1528字節
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 bytes                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         random bytes                          |
|                             (cont)                            |
|                              ....                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

握手簡圖

  • 未初始化階段(Uninitialized):協議版本在這個階段發送,客戶端和服務端都是未初始化的。客戶端在C0包中發送協議版本,若是服務端支持這個協議版本,其將會對應發送S0和S1;若是服務端不支持,服務端會採起合適的動做。在RTMP中,這個動做是停止鏈接。
  • 版本發送階段(Version Sent):在未初始化階段以後客戶端和服務端都處於版本發送階段。客戶端處於等待S1包,服務端處於等待C1包。在收到相應的等待的包後,客戶端發送C2而服務端會發送S2,而後進入確認發送階段。
  • 確認發送階段(Ack Sent):客戶端和服務端響應的等待S2和C2
  • 握手結束階段(Handshake Done):客戶端和服務端交換消息
+---------------+                             +---------------+
|    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
        |                      |                      |

分塊

握手以後,鏈接即可以進行多路傳輸塊流,每一個塊攜帶着一種信息流的一種類型,每塊流都有一個獨一無二的id即塊流id,經過網絡傳輸,每一個塊必須滿載,在接收端會根據id進行從新組裝。分塊容許經過更高階的協議進行小信息的分拆,好比能夠經過阻止大的低優先級消息(如視頻)而阻塞小的高優先級消息(如音頻或控制)。分塊一樣也容許更少的間接消耗將小的消息進行發送,好比塊頭包含有表明內容的壓縮信息,也可能反過來包含在信息之中。塊的大小是可配置的,大的塊可減小CPU使用,可是卻可能因爲較多的寫操做而帶來其餘內容低帶寬的延遲,小的塊不適合高比特流的傳輸,塊的大小在每一個方向上獨立保持。

塊格式

每一個塊包含頭和數據,頭包含三部分:

字段名 含義 大小
基礎頭(Basic Header) 塊流id和塊類型 1或3字節
消息頭(Message Header) 消息的主要內容 0,3,7或11字節
擴展時間戳(Extended Timestamp) 某種情境下的時間戳 0或4字節
塊數據(Chunk Data) 塊的載荷 可變字節
+---------------+----------------+--------------------+----------------+
|  Basic Header | Message Header | Extended Timestamp |   Chunk Data   |
+---------------+----------------+--------------------+----------------+
|                                                     |
| <------------------ Chunk Header -----------------> |
                              Chunk Format

1.塊基本頭

有三種類型:

字段名 含義 大小
塊流id(cs id) 數值2~63 6位
格式(fmt) 格式標識 2位
塊流id-64(cs id - 64) 數值減去64 8或16位

塊基礎頭1:

0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|fmt|   cs id   |
+-+-+-+-+-+-+-+-+

塊基礎頭2:

0                   1
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|fmt|     0     |   cs id - 64  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

塊基礎頭3:

0                   1                   2
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|fmt|     1     |           cs id - 64          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

2.塊消息頭

有四種類型:

Type 0:11字節

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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                   timestamp                   | message length|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   message length (cont)       |message type id| msg stream id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            message stream id (cont)           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                 Chunk Message Header - Type 0

Type 1:7字節

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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              timestamp delta                  | message length|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   message length (cont)       |message type id| 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                 Chunk Message Header - Type 1

Type 2:3字節

0                   1                   2      
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              timestamp delta                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         Chunk Message Header - Type 2

Type 3:沒有頭

公共頭字段:

字段名 含義 大小
事件戳間隔(timestamp delta) 類型1或類型2 3字節
消息長度(message length) 類型0或類型1 3字節
消息類型id(message type id) 類型0或類型1 1字節
消息流id(message stream id) 類型0 4字節

3.擴展時間戳

當時間戳大於 16777215(0xFFFFFF)時使用

協議控制消息

消息類型ID爲1,2,3,5,6是協議控制消息,這些內容須要塊流協議作基礎

設置塊大小

用於提示設置最大字節,最大128字節,服務端和客戶端能夠修改這個值,並升級另外一端的大小

停止消息

用於提示等待完成消息,以後丟棄部分接收的消息

識別

當接收字節和視窗大小相同時,客戶端或服務端必須發送給對應端確認消息

視窗識別大小

當進行確認時,客戶端或服務端發送給對應端視窗大小

設置端帶寬

客戶端和服務端向對應端發送輸出限制

RTMP消息格式

RTMP可用各類傳輸層協議

RTMP消息

消息能夠包含音頻,視頻,數據以及其餘消息格式


1.消息頭

包含消息類型,長度,時間戳,消息流id


2.消息載荷

實際消息承載內容

用戶控制消息

消息類型爲4

RTMP命令消息

客戶端和服務端的消息相互操做

消息類型


1.命令消息

AMF0格式值爲20 AMF3格式值爲17


2.數據消息

AMF0格式值爲18 AMF3格式值爲15


3.共享對象消息

AMF0格式值爲19 AMF3格式值爲16


4.音頻消息

值爲8


5.視頻消息

值爲9


6.聚合消息

值爲22


7.用戶控制消息事件

命令類型


1.網絡鏈接命令

鏈接 調用 建立流


2.網絡流命令

播放 播放2 刪除流 接收音頻 接收視頻 發佈 尋址 暫停

參考

相關文章
相關標籤/搜索