本文梳理了理解RTMP協議的基本概念
訪問 個人博客瞭解更多
下圖是播放器與 rtmp 服務端通訊的例子html
另外推薦閱讀 nginx-rtmp-module 源碼,好比,握手協議相關代碼在 ngx_rtmp_handshake.c
文件nginx
TCP 握手過程這裏不詳細展開,參考這篇文章 TCP 的那些事兒git
RTMP 握手起到驗證的做用,RTMP 握手方式主要分爲:簡單握手與複雜握手github
Adobe 協議中描述的是簡單握手,而 Adobe 產品 Flash Media Server 採用複雜握手的方式shell
與流程圖有點不一樣,握手的實際流程分三個步驟:服務器
我使用 Wireshark 抓包,驗證了過程(我使用 nginx-rtmp-module 作服務器,ffmpeg推流,VLC Media Play播放)網絡
報文的解釋:dom
C0 與 S0 +-+-+-+-+-+-+-+-+ | version | +-+-+-+-+-+-+-+-+
C0 與 S0tcp
C1 與 S1 +-+-+-+-+-+-+-+-+-+-+ | time (4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | zero (4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | random bytes | +-+-+-+-+-+-+-+-+-+-+ |random bytes(cont) | | .... | +-+-+-+-+-+-+-+-+-+-+
C1 與 S1post
C2 與 S2 +-+-+-+-+-+-+-+-+-+-+ | time (4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | time2(4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | random bytes | +-+-+-+-+-+-+-+-+-+-+ |random bytes(cont) | | .... | +-+-+-+-+-+-+-+-+-+-+
C2 與 S2
RTMP 是用於網絡傳輸的二進制協議,默認使用 Big-Endian 格式,由於 Big-Endian 格式在抓包時可讀性較好
對於複雜握手,不使用 Adobe 產品 FMS 的話,簡單瞭解便可
相對於簡單握手,複雜握手增長了嚴格的驗證,主要是 random 字段上進行更細化的劃分
1528Bytes隨機數的部分平均分紅兩部分,一部分764Bytes存儲public key(公共密鑰),另外一部分764Bytes存儲digest(密文,32字節)。
從二進制報文的角度,判斷複雜握手的特徵是,Version部分不爲0,服務器端可根據這個來判斷是否簡單握手或複雜握手。
握手的瞭解到這裏,下面繼續看看握手以後的步驟
RTMP 有一個重要的概念:Application Instance,直觀上,能夠體如今 rtmp 的 url 上
我測試的推流例子,用到的 url 爲: rtmp://192.168.23.152/live/movie
你們能夠注意到,上面 wireshark 對 rtmp 抓包的截圖中,握手後緊接一個 client->server 的報文 connect('live')
,
1909 36.398483095 192.168.23.152 192.168.23.152 RTMP 282 connect('live')
而這個 live
就是此次推流的 Application Instance
上面 wireshark 對 rtmp 抓包的截圖中,有下面兩行,第一行是 client->server,第二行是 server->client
1933 36.484940956 192.168.23.152 192.168.23.152 RTMP 105 Window Acknowledgement Size 5000000|createStream() 1935 36.485004644 192.168.23.152 192.168.23.152 RTMP 109 _result() 1946 36.528398367 192.168.23.152 192.168.23.152 RTMP 168 getStreamLength()|play('movie')|Set Buffer Length 1,3000ms
直觀地,rtmp://192.168.23.152/live/movie 的 movie 是此次拉流的 stream
。
createStream 命令用於建立邏輯通道,該通道用於傳輸視頻、音頻、metadata。在服務器的響應報文 _result() 中會返回Stream ID,用於惟一的標示該Stream。
getStreamLength 命令用來獲取 movie
的流的長度
Real Time Messaging Protocol (AMF0 Command getStreamLength()) RTMP Header RTMP Body String 'getStreamLength' Number 3 Null String 'movie' Real Time Messaging Protocol (AMF0 Command play('movie')) RTMP Header RTMP Body String 'play' Number 4 Null String 'movie' Number -2000
根據 Adobe’s Real Time Messaging Protocol 裏對 _result
命令的定義,上面 body 中第四個字段 "Number 1" 即是這次的 Stream ID
通常的 rtmp 鏈接的流程,都如上所示,後面即是命令與音視頻數據的消息,好比:
根據 Adobe’s Real Time Messaging Protocol
NetStream sends the deleteStream command when the NetStream object is getting destroyed.
當 NetStream 對象銷燬的時候發送刪除流命令。
好比,播放器客戶端中止播放,能夠刪除指定Stream ID的流。服務器不用對這條命令發送響應報文。