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