rtmp协议分析(三次握手)
RTMP詳細(xì)分析(Message 消息,Chunk分塊)
librtmp分析(發(fā)送數(shù)據(jù)包處理)
librtmp分析(接收數(shù)據(jù)包處理)
RTMP協(xié)議是Real Time Message Protocol(實(shí)時(shí)信息傳輸協(xié)議)的縮寫,它是由Adobe公司提出的一種應(yīng)
用層的協(xié)議,用來解決多媒體數(shù)據(jù)傳輸流的多路復(fù)用(Multiplexing)和分包(packetizing)的問題。隨
著VR技術(shù)的發(fā)展,視頻直播等領(lǐng)域逐漸活躍起來,RTMP作為業(yè)內(nèi)廣泛使用的協(xié)議也重新被相關(guān)開發(fā)者重
視起來。
目錄
- 1、介紹:
- 2.1、握手:
- 2.2、握手過程:
- 3.1 、C0和S0格式(簡(jiǎn)單握手):
- 3.2 、C1和S1格式(簡(jiǎn)單握手):
- 3.3 、C2和S2格式(簡(jiǎn)單握手):
- 4、復(fù)雜握手:
1、介紹:
RTMP協(xié)議是應(yīng)用層協(xié)議,是要靠底層可靠的傳輸層協(xié)議(通常是TCP)來保證信息傳輸?shù)目煽啃缘摹T?br /> 基于傳輸層協(xié)議的鏈接建立完成后,RTMP協(xié)議也要客戶端和服務(wù)器通過“握手”來建立基于傳輸層鏈接之
上的RTMP Connection鏈接,在Connection鏈接上會(huì)傳輸一些控制信息,如
SetChunkSize,SetACKWindowSize。其中CreateStream命令會(huì)創(chuàng)建一個(gè)Stream鏈接,用于傳輸具體的
音視頻數(shù)據(jù)和控制這些信息傳輸?shù)拿钚畔ⅰTMP協(xié)議傳輸時(shí)會(huì)對(duì)數(shù)據(jù)做自己的格式化,這種格式的消
息我們稱之為RTMP Message,而實(shí)際傳輸?shù)臅r(shí)候?yàn)榱烁玫貙?shí)現(xiàn)多路復(fù)用、分包和信息的公平性,發(fā)送
端會(huì)把Message劃分為帶有Message ID的Chunk,每個(gè)Chunk可能是一個(gè)單獨(dú)的Message,也可能是
Message的一部分,在接受端會(huì)根據(jù)chunk中包含的data的長(zhǎng)度,message id和message的長(zhǎng)度把
chunk還原成完整的Message,從而實(shí)現(xiàn)信息的收發(fā)。
2.1、握手:
一個(gè) RTMP 連接以握手開始。RTMP 的握手不同于其他協(xié)議? RTMP 握手由三個(gè)固定
長(zhǎng)度的塊組成,而不是像其他協(xié)議一樣的帶有報(bào)頭的可變長(zhǎng)度的塊。
客戶端 (發(fā)起連接請(qǐng)求的終端) 和服務(wù)器端各自發(fā)送相同的三塊。
客戶端發(fā)送的這些塊稱為C0、 C1 和 C2,服務(wù)器端發(fā)送的這些塊稱為 S0、
S1 和 S2。
2.2、握手過程:
本身并沒有規(guī)定這6個(gè)Message的具體傳輸順序,但RTMP協(xié)議的實(shí)現(xiàn)者需要保證這幾點(diǎn):
客戶端要等收到S1之后才能發(fā)送C2
客戶端要等收到S2之后才能發(fā)送其他信息(控制信息和真實(shí)音視頻等數(shù)據(jù))
服務(wù)端要等到收到C0之后發(fā)送S1
服務(wù)端必須等到收到C1之后才能發(fā)送S2
服務(wù)端必須等到收到C2之后才能發(fā)送其他信息(控制信息和真實(shí)音視頻等數(shù)據(jù))
理論上來講只要滿足以上條件,如何安排6個(gè)Message的順序都是可以的,但實(shí)際實(shí)現(xiàn)中為了在保證握手
的身份驗(yàn)證功能的基礎(chǔ)上盡量減少通信的次數(shù),一般的發(fā)送順序是這樣的,這一點(diǎn)可以通過wireshark抓推流包進(jìn)行驗(yàn)證:
握手流程圖:
Uninitialized (未初始化):協(xié)議的版本號(hào)在這個(gè)階段被發(fā)送。客戶端和服務(wù)器都是。
uninitialized (未初始化)狀態(tài)。之后客戶端在數(shù)據(jù)包 C0 中將協(xié)議版本號(hào)發(fā)出。如果服務(wù)器
支持這個(gè)版本,它將在回應(yīng)中發(fā)送S0 和 S1。如果不支持,服務(wù)器會(huì)才去適當(dāng)?shù)男袨檫M(jìn)
行響應(yīng)。在 RTMP 協(xié)議中,這個(gè)行為就是終止連接。
Version Sent (版本已發(fā)送):在未初始化狀態(tài)之后,客戶端和服務(wù)器都進(jìn)入 Version Sent
(版本已發(fā)送) 狀態(tài)。客戶端會(huì)等待接收數(shù)據(jù)包 S1 而服務(wù)器在等待 C1。一旦拿到期待的包,
客戶端會(huì)發(fā)送數(shù)據(jù)包 C2 而服務(wù)器發(fā)送數(shù)據(jù)包 S2。 (客戶端和服務(wù)器各自的)狀態(tài)隨即變?yōu)?br /> Ack Sent (確認(rèn)已發(fā)送 )。
Ack Sent (確認(rèn)已發(fā)送):客戶端和服務(wù)器分別等待 S2 和 C2。
Handshake Done (握手結(jié)束):客戶端和服務(wù)器可以開始交換消息了。
3.1 、C0和S0格式(簡(jiǎn)單握手):
C0 和 S0 包都是一個(gè)單一的八位字節(jié),以一個(gè)單獨(dú)的八位整型域進(jìn)行處理:
版本( 八位):在 C0 中,這一字段指示出客戶端要求的 RTMP 版本號(hào)。
在 S0 中,這一字段指示出服務(wù)器端選擇的 RTMP 版本號(hào)。版本號(hào)基本都是3。
0、1、2 這三個(gè)值是由早期其他產(chǎn)品使用的,是廢棄值。
4 - 31 被保留為RTMP 協(xié)議的未來實(shí)現(xiàn)版本使用。
32 - 255 不允許使用 (以區(qū)分開 RTMP 和其他常以一個(gè)可打印字符開始的文本協(xié)議)。
無法識(shí)別客戶端所請(qǐng)求版本號(hào)的服務(wù)器應(yīng)該以版本 3 響應(yīng), (收到響應(yīng)的) 客戶端可以選擇降低到版本 3,或者放棄握手。
3.2 、C1和S1格式(簡(jiǎn)單握手):
C1 和 S1 數(shù)據(jù)包的長(zhǎng)度都是 1536 字節(jié),分布如下:
Time (四個(gè)字節(jié)):這個(gè)字段包含一個(gè) timestamp,用于本終端發(fā)送的所有后續(xù)塊的時(shí)間
起點(diǎn)。這個(gè)值可以是 0。
Zero (四個(gè)字節(jié)):這個(gè)字段必須都是 0。
Random data (1528 個(gè)字節(jié)):這個(gè)字段可以包含任意值。終端需要區(qū)分出響應(yīng)來自它發(fā)
起的握手還是對(duì)端發(fā)起的握手,這個(gè)數(shù)據(jù)應(yīng)該發(fā)送一些足夠隨機(jī)的數(shù)。這個(gè)不需要對(duì)隨機(jī)數(shù)進(jìn)行加密保護(hù),也不需要?jiǎng)討B(tài)值。
3.3 、C2和S2格式(簡(jiǎn)單握手):
C2 和 S2 數(shù)據(jù)包長(zhǎng)度都是 1536 個(gè)節(jié),基本就是 S1 和 C1 的副本。分布如下:
Time (四個(gè)字節(jié)):這個(gè)字段必須包含終端在 S1 (給 C2) 或者 C1 (給 S2) 發(fā)的
timestamp。
Time2 (四個(gè)個(gè)節(jié)):這個(gè)字段必須包含終端先前發(fā)出數(shù)據(jù)包 (s1 或者 c1) timestamp。
Random echo (1528 個(gè)字節(jié)):這個(gè)字段必須包含終端發(fā)的 S1 (給 C2) 或者 S2 (給 C1)
的隨機(jī)數(shù)。
4、復(fù)雜握手:
復(fù)雜握手主要是增加了更嚴(yán)格的驗(yàn)證。
主要是將簡(jiǎn)單握手中1528Bytes隨機(jī)數(shù)的部分平均分成兩部分,
一部分764Bytes存儲(chǔ)public key(公共密鑰),另一部分
764Bytes存儲(chǔ)digest(密文, 32字節(jié))。
另外, 復(fù)雜握手還有一個(gè)明顯的特征就是: Version部分不為0,
服務(wù)器端可根據(jù)這個(gè)來判斷是否簡(jiǎn)單握手或復(fù)雜握手。
總結(jié)
以上是生活随笔為你收集整理的rtmp协议分析(三次握手)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 搭建srs服务器(rtmp)
- 下一篇: 关于Makefile,Makefile.