從使用者端發起播放請求,到rtrmp視訊流開始播放,大致經過了握手->建立連線->建立流->播放
這幾步比較重要的步驟。下面我將結合wireshark的抓包,對其中的每個流程進行分析和學習。
RTMP協定基於TCP,TCP建立連線有三次握手。在TCP連線建立以後,會再進行一次RTMP協定層次的握手。
TCP建立連線的三次握手如圖所示:
從wireshark的抓包中,也可以看到TCP的三次握手。
在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和S0都是單一的八位位元組,裡面包含著使用者端要求的RTMP版本號
C1和S1的長度都是1536個位元組,裡面包含著時間戳,4個位元組的0和1528個位元組隨機生成的資料
C2和S2的長度是1536個位元組,其中的資料包括:
握手完成後,使用者端會傳送connect命令到伺服器端,請求連線一個伺服器應用的範例。
connect訊息組成如下:
其中Command Object包含了多個欄位,來幫助使用者端和伺服器端的連線。
Command Object包含的欄位如下:
總的來說,就是包含了版本,流名稱,url,音視訊編碼等後面播放視訊流時所用的資訊,以保證後續伺服器端傳送的視訊資料可以正常播放。
wireshark抓包如下:
伺服器端收到connect命令後,傳送了幾條訊息給使用者端。如下圖所示:
Window Acknowledgement size的結構如下:
Window Acknowledgement size是伺服器端用來通知對端傳送和應答之間視窗大小的。
此例子中傳送的視窗大小為2500000。
該訊息裡限制對端輸出頻寬。
限制型別取以下值之一:
0 - Hard:對端應該限制其輸出頻寬到指示的視窗大小。
1 - Soft:對端應該限制其輸出頻寬到知識的視窗大小,或者已經有限制在其作用的話就取兩者之間的較小值。
2 - Dynamic:如果先前的限制型別為 Hard,處理這個訊息就好像它被標記為 Hard,否則的話忽略這個訊息。
設定塊大小,以通知對端新的最大塊大小,預設為128位元組。
Chunk是訊息的一段。訊息在網路傳送之前被拆分成很多小的部分。Chunk可以確保端到端交付所有訊息有序 timestamp,即使有很多不同的流。Chunk的格式如下:
在connect完成後就可以建立或者存取RTMP流了。
從抓包資料可以看到,伺服器端向用戶端傳送了三條命令,分別是Window Acknowledgement size,createStream和_checkbw。
主要的訊息是creatStream,使用者端傳送此訊息到伺服器端,建立一個邏輯通道,用於訊息通訊。音訊、視訊、後設資料均通過createStream建立的資料通道進行互動。createStream訊息的結構如下:
使用者端傳送createStream請求之後,伺服器端會反饋一個結果給使用者端,如果成功,則返回_result,如果失敗,則返回_error。
wireshark抓包資料如下:
在伺服器端返回的資料中,最後一個欄位為Stream ID,作為該Stream的唯一標識。此例子中返回的是1,後續的視訊或音訊的Stream ID就是1。
至此,使用者端和伺服器端的通道已經建立完成,接下來就可以進行資料的傳輸了。
createStream成功後,使用者端傳送play命令,通知伺服器端開始播放視訊流。
play訊息有7個欄位,其中最後3個為可選欄位。
從抓包資料可以看到,此次事務ID為5;流的名稱為「test」;start為-2000ms,即-2s,使用者首先嚐試播放流名欄位中定義的直播流。
使用者端傳送play命令來播放指定流後,就開始傳輸音視訊資料。後面就是使用者端按照流程對接收到的資料進行解協定,解封裝,解碼..........
........此處省略一萬字...........