rtmp協(xié)議詳解

版權(quán)聲明:本文為衛(wèi)偉學習總結(jié)文章,轉(zhuǎn)載請注明出處!

1.handshake
1.1.概述

rtmp連接從握手開始。它包含三個固定大小的塊。客戶端發(fā)送的三個塊命名為c0,c1,c2;服務端發(fā)送的三個塊命名為S0,S1,S2。
握手序列:

  • 客戶端通過發(fā)送c0和c1消息來啟動握手過程。客戶端必須收到S1消息,然后發(fā)送C2消息。客戶端必須接收到S2消息,然后發(fā)送其他數(shù)據(jù)。
  • 服務端必須接收到C0或者C1消息,然后發(fā)送S0和S1消息。服務端必須接收到C2消息,然后發(fā)送其他數(shù)據(jù)。
握手示意圖
1.2.complex handshake
1.2.1 C0和S0格式

C0和S0包由一個字節(jié)組成,下面是C0/S0包內(nèi)的字段:
  • version(1 byte) : RTMP的版本,一般為3
1.2.2 C1和S1格式

C1和S1包含兩部分數(shù)據(jù): key和digest,分別為如下:

key 和 digest 的順序是不確定的,也有可能是:(nginx-rtmp中是如下的順序):

764 bytes key 結(jié)構(gòu):
random-data: (offset) bytes
  • key-data: 128 bytes
  • random-data: (764 - offset - 128 - 4) bytes
  • offset: 4 bytes

764 bytes digest 結(jié)構(gòu):

  • offset: 4 bytes
  • random-data: (offset) bytes
  • digest-data: 32 bytes
  • random-data: (764 - 4 - offset - 32) bytes
1.2.3 C2和S2格式

hanshake:S0 + S1 + S2

1.3 simple handshake

1.3.1 C0和S0格式

version(1byte):版本。在C0包內(nèi),這個字段代表客戶端請求的RTMP版本號。在S0包內(nèi),這個字段代表服務端選擇的RTMP版本號。當前使用的版本是3。在版本0-2用在早期的產(chǎn)品中,如今已經(jīng)棄用;版本4-31被預留用于后續(xù)產(chǎn)品;版本32-255(為了區(qū)分RTMAP協(xié)議和文本協(xié)議,文本協(xié)議通常是可以打印字符)不允許使用。如果服務端無法識別客戶端的版本號,應該回復版本3。客戶端可以選擇降低到版本3,或者終止握手過程。

1.3.2 C1和S1格式

C1和S1包長度為1536字節(jié),包含以下字段:
  • time(4 bytes) : 本字段包含一個時間戳,客戶端應該使用此字段來標識所有流塊的時刻。時間戳取值可以為零或者任意值。為了同步多個塊流,客戶端可能希望多個塊流使用相同的時間戳。
  • zero (4 bytes): 本字段必須為零。
  • random (1528 bytes):本字段可以包含任意數(shù)據(jù)。由于握手的雙方需要區(qū)分另一端,此字段填充的數(shù)據(jù)必須足夠隨機(以防止與其他握手端混淆)。不過沒有必要為此使用加密數(shù)據(jù)或動態(tài)數(shù)據(jù)。
1.3.3 C2和S2格式

C2 和 S2 包長度為 1536 字節(jié),作為 C1 和 S1 的回應,包含以下字段:
  • time(4 bytes):本字段必須包含對端發(fā)送的時間戳。
  • time2(4 bytes):本字段必須包含時間戳,取值為接收對端發(fā)送過來的握手包的時刻。
  • random(1528 bytes):本字段必須包含對端發(fā)送過來的隨機數(shù)據(jù)。握手的雙方可以使用時間 1 和時間 2 字段來估算網(wǎng)絡連接的帶寬和/或延遲,但是不一定有用。
2.組塊
2.1塊格式
  • 塊的基本頭(1-3字節(jié)): 這個字段包含塊流ID和塊類型。塊的類型決定了編碼過的消息頭的格式。這個字段是一個變長字段,長度取決于塊流ID。
  • 消息頭(0,3,7,11字節(jié)):這個字段包含被發(fā)送的消息信息(無論是全部,還是部分)。字段長度由塊頭中的塊類型來決定。
  • 擴展時間戳(0,4字節(jié)): 這個字段是否存在取決于塊消息頭中編碼的時間戳。
  • 塊數(shù)據(jù)(可變大小):當前塊的有效數(shù)據(jù),上限為配置的最大塊大小。
2.2 Basic Header

包含chunk stream ID(流通道id)和chunk type(即fmt), chunk stream id 一般被簡寫為CSID,用來唯一標識一個特定的流通道,chunk type決定了后面的Message Header的格式。Basic Header的長度可能是1,2,或者3個字節(jié),其中chunk type的長度是固定的(占2位,單位是bit),Basic Header的長度取決于CSID的大小,在足夠存儲這兩個字段的前提下最好使用最少的字節(jié)從而減少由于引入Header增加的數(shù)據(jù)量。

RTMP協(xié)議支持用戶自定義[3,65599] 之間的 CSID,0, 1, 2 由協(xié)議保留表示特殊信息。0 代表 Basic Header 總共要占用 2 個字節(jié),CSID 在 [64,319] 之間; 1 代表占用 3 個字節(jié),CSID 在 [64,65599] 之間; 2 代表該 chunk 是控制信息和一些命令信息。

2.2.1 Basic Header: 1byte
2.2.2 Basic Header: 2 byte, csid == 0

CSID占14bit,此時協(xié)議將于chunk type所在字節(jié)的其他bit都置為0,剩下的一個字節(jié)表示CSID - 64,這樣共有8個bit來存儲 CSID,8 bit 可以表示 [0,255] 個數(shù),因此這種情況下 CSID 在 [64,319],其中 319 = 255 + 64。
1571629877(1).jpg
2.2.3 Basic Header: 3 bytes, csid == 1

CSID占22bit,此時協(xié)議將第一個字節(jié)的[2,8]bit置1,余下的16個bit表示CSID - 64,這樣共有16個bit來存儲CSID,16bit可以表示[0,65535]共 65536 個數(shù),因此這種情況下 CSID 在 [64,65599],其中65599=65535+64,需要注意的是,Basic Header是采用小端存儲的方式,越往后的字節(jié)數(shù)量級越高,因此通過3個字節(jié)的每一個bit的值來計算CSID時,應該是: <第三個字節(jié)的值> * 256 + <第二個字節(jié)的值> + 64.
2.3 Message Header

包含了要發(fā)送的實際消息(可能是完整的,也可能是一部分)的描述消息。Message Header的格式和長度取決于Basic Header的chunk type,即fmt,共有四種不同的格式。其中一種格式可以表示其他三種表示的所有數(shù)據(jù),但由于其他三種格式是基于對之前chunk的差量化的表示,因此可以更簡潔地表示相同的數(shù)據(jù),實際使用的時候還是應該采用盡量少的字節(jié)表示相同意義的數(shù)據(jù)。下面按字節(jié)從多到少的順序分別介紹這四種格式的 Message Header。

Message Header四種消息頭格式
一、Chunk Type(fmt)=0:11bytes

type=0時Message Header占用11個字節(jié),其他三種能表示的數(shù)據(jù)它都能表示,但Chunk stream的開始第一個chunk和頭信息中時間戳后退(即值與上一個chunk相比減少,通常在回退播放的時候會出現(xiàn)這種情況)的時候必須采用這種格式。

  • timestamp(時間戳):占用3個字節(jié),因此它最多能表示16777215=0xFFFFFF=2^24-1,當它的值超過這個最大值時,這三個字節(jié)都置為1,這樣實際的timestamp會轉(zhuǎn)存到 ExtendedTimestamp 字段中,接收端在判斷timestamp字段24個位都為1時就會去Extended Timestamp中解析實際的時間戳。
  • message length(消息數(shù)據(jù)長度):占用3個字節(jié),表示實際發(fā)送的消息的數(shù)據(jù)如音頻、視頻幀等數(shù)據(jù)的長度,單位時字節(jié)。注意這里時Message的長度,也就是chunk屬于Message的總長度,而不是chunk本事data的長度。
  • message type id(消息的類型id): 1個字節(jié),表示實際發(fā)送的數(shù)據(jù)的類型,如8代表音頻數(shù)據(jù),9代表視頻數(shù)據(jù)。
  • message stream id(消息的流id): 4個字節(jié),表示該chunk所在的流的ID,和Basic Header的CSID一樣,采用小端存儲方式。
二、Chunk Type(fmt)=1:7bytes

type為1時占用7個字節(jié),省去了表示message stream id的4個字節(jié),表示此chunk和上一次發(fā)的chunk所在的流相同,如果在發(fā)送端和對端有一個流鏈接的時候可以盡量采用這種格式。

  • timestamp delta:3 bytes,這里和type=0時不同,存儲的是和上一個chunk的時間差。類似上面提到的timestamp,當它的值超過3個字節(jié)所能表示的最大值時,三個字節(jié)都置為1,實際的時間戳差值就會轉(zhuǎn)存到Extended Timestamp字段中,接收端在判斷timestamp delta字段24個bit都為1時就會去Extended Timestamp 中解析實際的與上次時間戳的差值。
  • 其他字段與上面的解釋相同。
三、Chunk Type(fmt)=2: 3 bytes

type 為 2 時占用 3 個字節(jié),相對于 type = 1 格式又省去了表示消息長度的3個字節(jié)和表示消息類型的1個字節(jié),表示此 chunk和上一次發(fā)送的 chunk 所在的流、消息的長度和消息的類型都相同。余下的這三個字節(jié)表示 timestamp delta,使用同type=1。

四、Chunk Type(fmt)=3: 0byte

type=3時,為0字節(jié),表示這個chunk的Message Header和上一個是完全相同的。當它跟在type=0的chunk后面時,表示和前一
個 chunk 的時間戳都是相同。什么時候連時間戳都是相同呢?就是一個 Message 拆分成多個 chunk,這個 chunk 和上一個 chunk 同屬于一個 Message。而當它跟在 type = 1或 type = 2 的chunk后面時的chunk后面時,表示和前一個 chunk的時間戳的差是相同的。比如第一個 chunk 的 type = 0,timestamp = 100,第二個 chunk 的 type = 2,timestamp delta = 20,表示時間戳為 100 + 20 = 120,第三個 chunk 的 type = 3,表示 timestamp delta = 20,時間戳為 120 + 20 = 140。

2.4 Extended Timestamp(擴展時間戳)

在 chunk 中會有時間戳 timestamp 和時間戳差 timestamp delta,并且它們不會同時存在,只有這兩者之一大于3字節(jié)能表示的最大數(shù)值 0xFFFFFF = 16777215 時,才會用這個字段來表示真正的時間戳,否則這個字段為 0。擴展時間戳占 4 個字節(jié),
能表示的最大數(shù)值就是 0xFFFFFFFF = 4294967295。當擴展時間戳啟用時,timestamp字段或者timestamp delta要全置為1,而不是減去時間戳或者時間戳差的值。

2.5 chunk 示例
2.5.1 chunk 示例1

本示例展示了一個音頻消息流。流中包含有冗余信息。
  • 分析第一個chunk:
    -1 首先包含第一個Message的chunk的chunk type為0,因為它前面沒有可參考的chunk,timestamp為1000,表示時間戳。
    -2 type為0的header占用11個字節(jié),假定chunk stream id為3 < 127,因此basic header占用1個字節(jié);
    -3 再加上data的32字節(jié),因此第一個chunk共44個字節(jié)=11+1+32個字節(jié)。
  • 分析第二個chunk:
    -1. 第二個chunk與第一個chunk的cs id和chunk type id,以及data的長度都相同,因此采用類型2;
    -2. 可知timestamp delta = 1020 -1000 = 20;
    -3. 因此第二個chunk占用36 = 3 (message header) + 1(basic header) +32
  • 分析第三個chunk:
    -1. 第三個 chunk 和第二個 chunk 的 cs id ,chunk type id,以及 data 的長度和時間戳的差值都相同,因此采用 類型 3,省去全部的 Message Header 的信息;
    -2. 因此占用 33 = 1 + 32
  • 分析第四個chunk:
    -1.第四個 chunk 和第三個 chunk 情況相同,也占用 33 = 1 + 32 個字節(jié)。

最后實際發(fā)送的chunk如下面表格所示,該表格展示了由此音頻流產(chǎn)生的塊信息。從第 3 條信息開始,數(shù)據(jù)傳輸達到最大優(yōu)化。每條消息的頭部只增加了 1 字節(jié)長度。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內(nèi)容

  • 實時消息協(xié)議---流的分塊 版權(quán)聲明: 版權(quán)(c)2009 Adobe系統(tǒng)有限公司。全權(quán)所有。 摘要: 本備忘錄描...
    一個人zy閱讀 1,923評論 0 9
  • 個人翻譯,轉(zhuǎn)載請注明出處,謝謝! Adobe's Real Time Messaging Protocol 摘要 ...
    SniperPan閱讀 2,770評論 1 17
  • RTMP協(xié)議是Real Time Message Protocol(實時信息傳輸協(xié)議)的縮寫,它是由Adobe公司...
    iOS小肖閱讀 3,519評論 0 4
  • 作者原創(chuàng),轉(zhuǎn)載請聯(lián)系作者 RTMP簡介 Real Time Messaging Protocol(實時消息傳送協(xié)議...
    Alfie20閱讀 1,388評論 0 4
  • @TOC 1. RTMP協(xié)議簡介 RTMP協(xié)議是一個互聯(lián)網(wǎng)TCP/IP五層體系結(jié)構(gòu)中應用層的協(xié)議。RTMP協(xié)議中基...
    孔雨露閱讀 742評論 0 1