RTMP协议学习——从握手到播放
從客戶端發起播放請求,到rtrmp視頻流開始播放,大致經過了握手->建立連接->創建流->播放這幾步比較重要的步驟。下面我將結合wireshark的抓包,對其中的每個流程進行分析和學習。
握手
RTMP協議基于TCP,TCP建立連接有三次握手。在TCP連接建立以后,會再進行一次RTMP協議層次的握手。
TCP握手
TCP建立連接的三次握手如圖所示:
從wireshark的抓包中,也可以看到TCP的三次握手。
RTMP握手
在TCP建立連接成功后,rtmp會再進行三次握手。
可以通過在wireshark的過濾器中輸入rtmpt來過濾RTMP協議的數據,如圖所示:
客戶端首先發送C0、C1到服務器。其中C1的大小是固定的,為1536個字節。服務端收到C0,C1后,發送S0,S1給客戶端,S1的大小和C1一樣,為1536個字節。服務端收齊C0,C1后,發送S2給客戶端,客戶端收齊S0,S1后,發送C2給服務端。C2和S2的大小也為1536個字節。可以看出來,rtmp協議握手交換數據報文的大小是固定的。
下圖是引自wiki,可以很清晰的看到客戶端和服務端的交互流程和包之間的關系:
C0 and S0
C0和S0都是單一的八位字節,里面包含著客戶端要求的RTMP版本號
C1 and S1
C1和S1的長度都是1536個字節,里面包含著時間戳,4個字節的0和1528個字節隨機生成的數據
C2 and S2
C2和S2的長度是1536個字節,其中的數據包括:
- time:終端在 S1 (給 C2) 或者 C1 (給 S2) 發的 timestamp。
- time2:終端先前發出數據包 (S1 或者 C1) timestamp。
- random echo:終端發的 S1 (給 C2) 或者 S2 (給 C1) 的隨機數據。
connect
客戶端
握手完成后,客戶端會發送connect命令到服務端,請求連接一個服務器應用的實例。
connect消息組成如下:
其中Command Object包含了多個字段,來幫助客戶端和服務端的連接。
Command Object包含的字段如下:
- app:客戶端連接到服務器應用端的名字
- flashver:Flash Player 版本號。和ApplicationScript getversion() 方法返回的是同一個字符串。
- swfUrl:進行當前連接的 SWF 文件源地址。
- tcUrl:服務器 URL。
- fpad:代理標志,如果使用了代理就是 true。
- audioCodecs:表明客戶端所支持的音頻編碼。
- videoCodecs:表明支持的視頻編碼。
- videoFunction:表明所支持的特殊視頻方法。
- pageUrl:SWF 文件所加載的網頁 URL。
- objectEncoding:AMF 編碼方法。
總的來說,就是包含了版本,流名稱,url,音視頻編碼等后面播放視頻流時所用的信息,以保證后續服務端發送的視頻數據可以正常播放。
wireshark抓包如下:
服務端
服務端收到connect命令后,發送了幾條消息給客戶端。如下圖所示:
Window Acknowledgement size
Window Acknowledgement size的結構如下:
Window Acknowledgement size是服務器端用來通知對端發送和應答之間窗口大小的。
此例子中發送的窗口大小為2500000。
Set Peer Bandwidth
該消息里限制對端輸出帶寬。
限制類型取以下值之一:
-
0 - Hard:對端應該限制其輸出帶寬到指示的窗口大小。
-
1 - Soft:對端應該限制其輸出帶寬到知識的窗口大小,或者已經有限制在其作用的話就取兩者之間的較小值。
-
2 - Dynamic:如果先前的限制類型為 Hard,處理這個消息就好像它被標記為 Hard,否則的話忽略這個消息。
Set Chunk Size
設置塊大小,以通知對端新的最大塊大小,默認為128字節。
Chunk是消息的一段。消息在網絡發送之前被拆分成很多小的部分。Chunk可以確保端到端交付所有消息有序 timestamp,即使有很多不同的流。Chunk的格式如下:
createStream
在connect完成后就可以創建或者訪問RTMP流了。
從抓包數據可以看到,服務端向客戶端發送了三條命令,分別是Window Acknowledgement size,createStream和_checkbw。
- Window Acknowledgement size是對之前服務端發送的Set Peer Bandwidth消息的應答。
- _checkbw用于檢查帶寬,來評估與服務器的連接質量和帶寬。
主要的消息是creatStream,客戶端發送此消息到服務端,創建一個邏輯通道,用于消息通信。音頻、視頻、元數據均通過createStream創建的數據通道進行交互。createStream消息的結構如下:
客戶端發送createStream請求之后,服務端會反饋一個結果給客戶端,如果成功,則返回_result,如果失敗,則返回_error。
wireshark抓包數據如下:
在服務端返回的數據中,最后一個字段為Stream ID,作為該Stream的唯一標識。此例子中返回的是1,后續的視頻或音頻的Stream ID就是1。
至此,客戶端和服務端的通道已經建立完成,接下來就可以進行數據的傳輸了。
play
createStream成功后,客戶端發送play命令,通知服務端開始播放視頻流。
play消息有7個字段,其中最后3個為可選字段。
- Command Name: String類型,命令的名稱,為“play”。
- Transaction ID: Number類型,事務ID。
- Command Object:命令信息不存在。設為 null 類型。
- Stream Name: String類型,要播放流的名字。
- Start(可選): Number類型,以秒為單位定義開始時間,默認值為 -2,表示用戶首先嘗試播放流名字段中定義的直播流。
- Duration(可選): Number類型,以秒為單位定義了回放的持續時間。默認值為 -1。-1 值意味著一個直播流會一直播放直到它不再可用或者一個錄制流一直播放直到結束。
- Reset(可選): Boolean類型,定義了是否對以前的播放列表進行 flush。
wireshark抓包數據為:
從抓包數據可以看到,此次事務ID為5;流的名稱為“test”;start為-2000ms,即-2s,用戶首先嘗試播放流名字段中定義的直播流。
客戶端發送play命令來播放指定流后,就開始傳輸音視頻數據。后面就是客戶端按照流程對接收到的數據進行解協議,解封裝,解碼..........
........此處省略一萬字...........
總結
以上是生活随笔為你收集整理的RTMP协议学习——从握手到播放的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 重温《庆余年》第一集!小范闲为什么去澹州
- 下一篇: 嗨,别着急做度量,平台工程需要先从“数据