RTMP協(xié)議抓包分析拉流過程

基本概念:

RTMP協(xié)議規(guī)定,播放一個流媒體有兩個前提步驟:
第一步,建立一個網(wǎng)絡(luò)連接(NetConnection)。
第二步,建立一個網(wǎng)絡(luò)流(NetStream)。
網(wǎng)絡(luò)連接代表服務(wù)器端應(yīng)用程序和客戶端之間基礎(chǔ)的連通關(guān)系,網(wǎng)絡(luò)流代表了發(fā)送多媒體數(shù)據(jù)的通道。服務(wù)器和客戶端之間只能建立一個網(wǎng)絡(luò)連接,但是基于該連接可以創(chuàng)建很多網(wǎng)絡(luò)流。

播放一個RTMP協(xié)議的流媒體需要經(jīng)過四個階段:

  1. 握手階段
  2. 建立連接階段
  3. 建立流階段
  4. 播放階段
    RTMP連接都是以握手作為開始的,建立連接階段用于建立客戶端與服務(wù)器之間的“網(wǎng)絡(luò)連接”。
    建立流階段用于建立客戶端與服務(wù)器之間的“網(wǎng)絡(luò)流”。
    播放階段用于傳輸視音頻數(shù)據(jù)。

下面是使用librtmp執(zhí)行拉流過程的API調(diào)用流,如下:


image.png

抓包分析:

RTMP定義了較為完善的協(xié)議標準,但是每種播放工具的實現(xiàn)略有差異,下面是我使用VLC播放器拉流時抓取的報文,使用wireshark分析過程整理為下面的圖文。

先看一張總覽圖,圖中顯示的報文和時序包含了握手、建立連接、建立流和播放階段,如下:


image.png

還有申明下,以下的流程是根據(jù)實際抓包情況分析出來的,由于不同的工具省略了一些不必要的步驟,故不代表標準結(jié)果,僅供參考。

握手階段:

由于講解握手過程的文檔資料比較多,我這里就不重復描述了,摘圖如下:


image.png

個人認為這張圖是最符合標準時序的,細節(jié)拿捏得非常講究,雖然很多實現(xiàn)簡化了流程。

建立連接階段:

包括以下報文和步驟:

  1. 客戶端發(fā)起連接請求
  2. 服務(wù)器設(shè)置客戶端的應(yīng)答窗口大小
  3. 服務(wù)器設(shè)置客戶端的發(fā)送帶寬大小
  4. 服務(wù)器設(shè)置客戶端的接收塊大小
  5. 服務(wù)器響應(yīng)連接結(jié)果
  6. 客戶端設(shè)置服務(wù)器的應(yīng)答窗口大小
客戶端發(fā)起連接請求:

協(xié)議截圖如下:


image.png

協(xié)議方向:客戶端 -> 服務(wù)器
塊頭字段:
???? HeaderType: 0
???? CSID: 3
???? 時間戳:0
???? BodySize: 201
???? TypeID: 0x14
???? Stream ID: 0
負載格式:AMF0表示,connect 1 object1
???? object1屬性列表:
???? ???? "app": "live"
???? ???? "flashVer": "LNX 9,0,124,2"
???? ???? "tcUrl": "rtmp://127.0.0.1:1935/live"
???? ???? "fpad": false
???? ???? "capabilities": 15,
???? ???? "audioCodes": 4071,
???? ???? "videoCodes": 252,
???? ???? "videoFunction": 1,
???? ???? End Of Object Marker

服務(wù)器設(shè)置客戶端的應(yīng)答窗口大?。?/h6>

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 2
???? 時間戳:0
???? BodySize: 4
???? TypeID: 0x05
???? Stream ID: 0
負載格式:4字節(jié)整型表示,如5000000

服務(wù)器設(shè)置客戶端的發(fā)送帶寬大小:

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 2
???? 時間戳:0
???? BodySize: 5
???? TypeID: 0x06
???? Stream ID: 0
負載格式:5字節(jié)整型表示,前4字節(jié)為帶寬,后1字節(jié)為標志,如5000000, 2(動態(tài)調(diào)整)

服務(wù)器設(shè)置客戶端的接收塊大?。?/h6>

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 2
???? 時間戳:0
???? BodySize: 4
???? TypeID: 0x01
???? Stream ID: 0
負載格式:4字節(jié)整型表示,如4096

服務(wù)器響應(yīng)連接結(jié)果:

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 3
???? 時間戳:0
???? BodySize: 190
???? TypeID: 0x14
???? Stream ID: 0
負載格式:AMF0表示,_result 1 object1 object2
???? object1屬性列表:
???? ???? "fmsVer": "FMS/3,0,1,123"
???? ???? "capabilities": 31,
???? ???? End Of Object Marker
???? object2屬性列表:
???? ???? "level": "status"
???? ???? "code": "NetConnection.Connect.Success",
???? ???? "description": "Connection succeeded.",
???? ???? "objectEncoding": 0
???? ???? End Of Object Marker

客戶端設(shè)置服務(wù)器的應(yīng)答窗口大?。?/h6>

協(xié)議截圖如下:


image.png

協(xié)議方向:客戶端 -> 服務(wù)器
塊頭字段:
???? HeaderType: 0
???? CSID: 2
???? 時間戳:0
???? BodySize: 4
???? TypeID: 0x05
???? Stream ID: 0
負載格式:4字節(jié)整型表示,如5000000

建立流階段:

包括以下報文和步驟:

  1. 客戶端發(fā)起創(chuàng)建流請求
  2. 服務(wù)器響應(yīng)創(chuàng)建流結(jié)果
客戶端發(fā)起創(chuàng)建流請求:

協(xié)議截圖如下:


image.png

協(xié)議方向:客戶端 -> 服務(wù)器
塊頭字段:
???? HeaderType: 1
???? CSID: 3
???? 時間戳:0
???? BodySize: 25
???? TypeID: 0x14
負載格式:AMF0表示,createStream 2 object(Null)

服務(wù)器響應(yīng)創(chuàng)建流結(jié)果:

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 3
???? 時間戳:0
???? BodySize: 29
???? TypeID: 0x14
???? Stream ID: 0
負載格式:AMF0表示,_result 2 object(Null) Number(1)

播放階段:

包括以下報文和步驟:

  1. 客戶端發(fā)起播放節(jié)目請求
  2. 客戶端通知服務(wù)器設(shè)置緩沖區(qū)大小
  3. 服務(wù)器通知客戶端啟動流
  4. 服務(wù)器通知客戶端流進入播放狀態(tài)
  5. 服務(wù)器向客戶端發(fā)送媒體元數(shù)據(jù)
  6. 服務(wù)器向客戶端發(fā)送媒體數(shù)據(jù)
客戶端發(fā)起播放節(jié)目請求:

協(xié)議截圖如下:


image.png

協(xié)議方向:客戶端 -> 服務(wù)器
塊頭字段:
???? HeaderType: 0
???? CSID: 8
???? 時間戳:0
???? BodySize: 30
???? TypeID: 0x14
???? Stream ID: 1
負載格式:AMF0表示,play 4 Object(Null) String節(jié)目ID("a") Number開始時間(-2000)

客戶端通知服務(wù)器設(shè)置緩沖區(qū)大?。?/h6>

協(xié)議截圖如下:


image.png

協(xié)議方向:客戶端 -> 服務(wù)器
塊頭字段:
???? HeaderType: 1
???? CSID: 2
???? 時間戳:1
???? BodySize: 10
???? TypeID: 0x04
負載格式:Event Type,2字節(jié)的類型(3) 4字節(jié)的流ID(1) 4字節(jié)的MS時間單位(3000)

服務(wù)器通知客戶端啟動流:

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 2
???? 時間戳:0
???? BodySize: 6
???? TypeID: 0x04
負載格式:Event Type,2字節(jié)的類型(0) 4字節(jié)的流ID(1)

服務(wù)器通知客戶端流進入播放狀態(tài):

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 5
???? 時間戳:0
???? BodySize: 96
???? TypeID: 0x14
???? Stream ID: 1
負載格式:AMF0表示,onStatus 0 Object1(Null) object2
???? object2屬性列表:
???? ???? "level": "status"
???? ???? "code": "NetStream.Play.Start",
???? ???? "description": "Start live",
???? ???? End Of Object Marker

服務(wù)器向客戶端發(fā)送媒體元數(shù)據(jù):

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 5
???? 時間戳:0
???? BodySize: 387
???? TypeID: 0x12
???? Stream ID: 1
負載格式:AMF0表示,onMetaData object
???? object屬性列表:
???? ???? "Server": "NGINX RTMP"
???? ???? "width": 480,
???? ???? "height": 270,
???? ???? "displayWidth": 480,
???? ???? "displayHeight": 270,
???? ???? "duration": 0,
???? ???? "framerate": 16,
???? ???? "fps": 16,
???? ???? "videodatarate": 193,
???? ???? "videocodeid": 7,
???? ???? "audiodatarate": 52,
???? ???? "audiocodeid": 10,
???? ???? "profile": "",
???? ???? "level": "",
???? ???? End Of Object Marker

服務(wù)器向客戶端發(fā)送媒體數(shù)據(jù):

協(xié)議截圖如下:


image.png

協(xié)議方向:服務(wù)器 -> 客戶端
塊頭字段:
???? HeaderType: 0
???? CSID: 6
???? 時間戳:0
???? BodySize: 209
???? TypeID: 0x08
???? Stream ID: 1
負載格式:格式頭,媒體數(shù)據(jù)

流程時序:

結(jié)合以上分析,總結(jié)時序圖如下:


拉流時序.png

另外,關(guān)于HeaderType和CSID的運用,先歸納使用情況:
0x14(connect) HeaderType: 0 CSID: 3
0x05(Ack Window Size) HeaderType: 0 CSID: 2
0x06(BrandWidth) HeaderType: 0 CSID: 2
0x01(ChunkSize) HeaderType: 0 CSID: 2
0x14(connect _result) HeaderType: 0 CSID: 3
0x14(createStream) HeaderType: 1 CSID: 3
0x14(createStream _result) HeaderType: 0 CSID: 3
0x14(play) HeaderType: 0 CSID: 8
0x04(SetBufferMS) HeaderType: 1 CSID: 2
0x04(Stream Begin) HeaderType: 0 CSID: 2
0x14(play onStatus) HeaderType: 0 CSID: 5
0x12(onMetaData) HeaderType: 0 CSID: 5
0x08(audioData) HeaderType: 0 CSID: 6
0x09(videoData) HeaderType: 0 CSID: 7

總結(jié):
關(guān)于HeaderType的運用,有以下規(guī)則:
createStream使用1號HeaderType,借用3號CSID之前的StreamID。
SetBufferMS使用1號HeaderType。
audioData和videoData視情況使用0、1、2、3號HeaderType。
關(guān)于CSID的運用,有以下規(guī)則:

  1. 0x01~0x06命令用2號CSID。
  2. 大部分0x14命令用3號CSID,但有例外,如play用8號CSID,play onStatus用5號CSID。
  3. 0x12媒體元數(shù)據(jù)用5號CSID。
  4. 0x08音頻數(shù)據(jù)用6號CSID。
  5. 0x09視頻數(shù)據(jù)用7號CSID。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • RTMP協(xié)議是Real Time Message Protocol(實時信息傳輸協(xié)議)的縮寫,它是由Adobe公司...
    iOS小肖閱讀 3,653評論 0 4
  • RTMP協(xié)議是Real Time Message Protocol(實時信息傳輸協(xié)議)的縮寫,它是由Adobe公司...
    日月當頭閱讀 40,088評論 6 67
  • 本文轉(zhuǎn)自:http://www.itdecent.cn/p/b2144f9bbe28 RTMP協(xié)議是Real T...
    pandazhong閱讀 413評論 0 0
  • 一、RTMP 協(xié)議簡介 RTMP(Real-Time Messaging Protocol),譯為:實時消息傳輸協(xié)...
    村口大白楊閱讀 1,266評論 0 1
  • RTMP協(xié)議是Real Time Message Protocol(實時信息傳輸協(xié)議)的縮寫,它是由Adobe公司...
    我是李小胖閱讀 1,299評論 0 0

友情鏈接更多精彩內(nèi)容