RTMP是Real Time Messaging Protocol的簡稱,是基於什麼時候的傳輸層協議上(如tcp協議)的應用層級別的協議,其設計是爲了組包多媒體傳輸流(如視頻,音頻以及交互內容)前端
RTMP協議是由Adobe公司提出的一種應用層的協議,上面引述的是RTMP官方文檔的introduction部分,其目的是爲了給諸如視頻、音頻以及數據消息通訊雙方提供實時的信息雙向流。RTMP在實現上對不一樣類型的消息實施不一樣的權重,這樣能夠實現對當傳輸量受限時的底層流傳輸消息進行排隊。git
全部的整字段以字節序來傳輸,而且是大端排列,不作特殊說明均爲十進制。時間戳以毫秒記,從0開始,32位長;時間間隔用毫秒的無符號整數表示,多是24或32位長度github
儘管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是一個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是一個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是一個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) | | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+---------------+ +---------------+ | 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可用各類傳輸層協議
消息能夠包含音頻,視頻,數據以及其餘消息格式
1.消息頭
包含消息類型,長度,時間戳,消息流id
2.消息載荷
實際消息承載內容
消息類型爲4
客戶端和服務端的消息相互操做
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 刪除流 接收音頻 接收視頻 發佈 尋址 暫停