rtmp協(xié)議詳解

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

1.handshake
1.1.概述

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

  • 客戶端通過發(fā)送c0和c1消息來啟動(dòng)握手過程湖笨。客戶端必須收到S1消息蹦骑,然后發(fā)送C2消息慈省。客戶端必須接收到S2消息眠菇,然后發(fā)送其他數(shù)據(jù)边败。
  • 服務(wù)端必須接收到C0或者C1消息袱衷,然后發(fā)送S0和S1消息。服務(wù)端必須接收到C2消息笑窜,然后發(fā)送其他數(shù)據(jù)致燥。
握手示意圖
1.2.complex handshake
1.2.1 C0和S0格式

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

C1和S1包含兩部分?jǐn)?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)搬葬,這個(gè)字段代表客戶端請(qǐng)求的RTMP版本號(hào)。在S0包內(nèi)艳悔,這個(gè)字段代表服務(wù)端選擇的RTMP版本號(hào)。當(dāng)前使用的版本是3女仰。在版本0-2用在早期的產(chǎn)品中猜年,如今已經(jīng)棄用;版本4-31被預(yù)留用于后續(xù)產(chǎn)品疾忍;版本32-255(為了區(qū)分RTMAP協(xié)議和文本協(xié)議乔外,文本協(xié)議通常是可以打印字符)不允許使用。如果服務(wù)端無(wú)法識(shí)別客戶端的版本號(hào)一罩,應(yīng)該回復(fù)版本3杨幼。客戶端可以選擇降低到版本3聂渊,或者終止握手過程差购。

1.3.2 C1和S1格式

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

C2 和 S2 包長(zhǎng)度為 1536 字節(jié)陈惰,作為 C1 和 S1 的回應(yīng),包含以下字段:
  • time(4 bytes):本字段必須包含對(duì)端發(fā)送的時(shí)間戳闭专。
  • time2(4 bytes):本字段必須包含時(shí)間戳奴潘,取值為接收對(duì)端發(fā)送過來的握手包的時(shí)刻旧烧。
  • random(1528 bytes):本字段必須包含對(duì)端發(fā)送過來的隨機(jī)數(shù)據(jù)。握手的雙方可以使用時(shí)間 1 和時(shí)間 2 字段來估算網(wǎng)絡(luò)連接的帶寬和/或延遲画髓,但是不一定有用掘剪。
2.組塊
2.1塊格式
  • 塊的基本頭(1-3字節(jié)): 這個(gè)字段包含塊流ID和塊類型。塊的類型決定了編碼過的消息頭的格式奈虾。這個(gè)字段是一個(gè)變長(zhǎng)字段夺谁,長(zhǎng)度取決于塊流ID。
  • 消息頭(0肉微,3匾鸥,7,11字節(jié)):這個(gè)字段包含被發(fā)送的消息信息(無(wú)論是全部碉纳,還是部分)勿负。字段長(zhǎng)度由塊頭中的塊類型來決定。
  • 擴(kuò)展時(shí)間戳(0劳曹,4字節(jié)): 這個(gè)字段是否存在取決于塊消息頭中編碼的時(shí)間戳奴愉。
  • 塊數(shù)據(jù)(可變大小):當(dāng)前塊的有效數(shù)據(jù)铁孵,上限為配置的最大塊大小锭硼。
2.2 Basic Header

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

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

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

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

CSID占22bit,此時(shí)協(xié)議將第一個(gè)字節(jié)的[2,8]bit置1得滤,余下的16個(gè)bit表示CSID - 64陨献,這樣共有16個(gè)bit來存儲(chǔ)CSID,16bit可以表示[0,65535]共 65536 個(gè)數(shù)懂更,因此這種情況下 CSID 在 [64,65599]岗仑,其中65599=65535+64鄙陡,需要注意的是钝腺,Basic Header是采用小端存儲(chǔ)的方式啦辐,越往后的字節(jié)數(shù)量級(jí)越高,因此通過3個(gè)字節(jié)的每一個(gè)bit的值來計(jì)算CSID時(shí)慷暂,應(yīng)該是: <第三個(gè)字節(jié)的值> * 256 + <第二個(gè)字節(jié)的值> + 64.
2.3 Message Header

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

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

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

  • timestamp(時(shí)間戳):占用3個(gè)字節(jié),因此它最多能表示16777215=0xFFFFFF=2^24-1隅忿,當(dāng)它的值超過這個(gè)最大值時(shí)心剥,這三個(gè)字節(jié)都置為1,這樣實(shí)際的timestamp會(huì)轉(zhuǎn)存到 ExtendedTimestamp 字段中背桐,接收端在判斷timestamp字段24個(gè)位都為1時(shí)就會(huì)去Extended Timestamp中解析實(shí)際的時(shí)間戳优烧。
  • message length(消息數(shù)據(jù)長(zhǎng)度):占用3個(gè)字節(jié),表示實(shí)際發(fā)送的消息的數(shù)據(jù)如音頻链峭、視頻幀等數(shù)據(jù)的長(zhǎng)度畦娄,單位時(shí)字節(jié)。注意這里時(shí)Message的長(zhǎng)度,也就是chunk屬于Message的總長(zhǎng)度熙卡,而不是chunk本事data的長(zhǎng)度杖刷。
  • message type id(消息的類型id): 1個(gè)字節(jié),表示實(shí)際發(fā)送的數(shù)據(jù)的類型驳癌,如8代表音頻數(shù)據(jù)滑燃,9代表視頻數(shù)據(jù)。
  • message stream id(消息的流id): 4個(gè)字節(jié)喂柒,表示該chunk所在的流的ID不瓶,和Basic Header的CSID一樣,采用小端存儲(chǔ)方式灾杰。
二蚊丐、Chunk Type(fmt)=1:7bytes

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

  • timestamp delta:3 bytes昭娩,這里和type=0時(shí)不同凛篙,存儲(chǔ)的是和上一個(gè)chunk的時(shí)間差。類似上面提到的timestamp栏渺,當(dāng)它的值超過3個(gè)字節(jié)所能表示的最大值時(shí)呛梆,三個(gè)字節(jié)都置為1,實(shí)際的時(shí)間戳差值就會(huì)轉(zhuǎn)存到Extended Timestamp字段中磕诊,接收端在判斷timestamp delta字段24個(gè)bit都為1時(shí)就會(huì)去Extended Timestamp 中解析實(shí)際的與上次時(shí)間戳的差值填物。
  • 其他字段與上面的解釋相同。
三霎终、Chunk Type(fmt)=2: 3 bytes

type 為 2 時(shí)占用 3 個(gè)字節(jié)滞磺,相對(duì)于 type = 1 格式又省去了表示消息長(zhǎng)度的3個(gè)字節(jié)和表示消息類型的1個(gè)字節(jié),表示此 chunk和上一次發(fā)送的 chunk 所在的流莱褒、消息的長(zhǎng)度和消息的類型都相同击困。余下的這三個(gè)字節(jié)表示 timestamp delta,使用同type=1广凸。

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

type=3時(shí),為0字節(jié)谅海,表示這個(gè)chunk的Message Header和上一個(gè)是完全相同的目派。當(dāng)它跟在type=0的chunk后面時(shí),表示和前一
個(gè) chunk 的時(shí)間戳都是相同胁赢。什么時(shí)候連時(shí)間戳都是相同呢企蹭?就是一個(gè) Message 拆分成多個(gè) chunk白筹,這個(gè) chunk 和上一個(gè) chunk 同屬于一個(gè) Message。而當(dāng)它跟在 type = 1或 type = 2 的chunk后面時(shí)的chunk后面時(shí)谅摄,表示和前一個(gè) chunk的時(shí)間戳的差是相同的徒河。比如第一個(gè) chunk 的 type = 0,timestamp = 100送漠,第二個(gè) chunk 的 type = 2顽照,timestamp delta = 20,表示時(shí)間戳為 100 + 20 = 120闽寡,第三個(gè) chunk 的 type = 3代兵,表示 timestamp delta = 20,時(shí)間戳為 120 + 20 = 140。

2.4 Extended Timestamp(擴(kuò)展時(shí)間戳)

在 chunk 中會(huì)有時(shí)間戳 timestamp 和時(shí)間戳差 timestamp delta爷狈,并且它們不會(huì)同時(shí)存在植影,只有這兩者之一大于3字節(jié)能表示的最大數(shù)值 0xFFFFFF = 16777215 時(shí),才會(huì)用這個(gè)字段來表示真正的時(shí)間戳涎永,否則這個(gè)字段為 0思币。擴(kuò)展時(shí)間戳占 4 個(gè)字節(jié),
能表示的最大數(shù)值就是 0xFFFFFFFF = 4294967295羡微。當(dāng)擴(kuò)展時(shí)間戳啟用時(shí)谷饿,timestamp字段或者timestamp delta要全置為1,而不是減去時(shí)間戳或者時(shí)間戳差的值妈倔。

2.5 chunk 示例
2.5.1 chunk 示例1

本示例展示了一個(gè)音頻消息流博投。流中包含有冗余信息。
  • 分析第一個(gè)chunk:
    -1 首先包含第一個(gè)Message的chunk的chunk type為0盯蝴,因?yàn)樗懊鏇]有可參考的chunk贬堵,timestamp為1000,表示時(shí)間戳结洼。
    -2 type為0的header占用11個(gè)字節(jié),假定chunk stream id為3 < 127叉跛,因此basic header占用1個(gè)字節(jié);
    -3 再加上data的32字節(jié)松忍,因此第一個(gè)chunk共44個(gè)字節(jié)=11+1+32個(gè)字節(jié)。
  • 分析第二個(gè)chunk:
    -1. 第二個(gè)chunk與第一個(gè)chunk的cs id和chunk type id筷厘,以及data的長(zhǎng)度都相同鸣峭,因此采用類型2;
    -2. 可知timestamp delta = 1020 -1000 = 20;
    -3. 因此第二個(gè)chunk占用36 = 3 (message header) + 1(basic header) +32
  • 分析第三個(gè)chunk:
    -1. 第三個(gè) chunk 和第二個(gè) chunk 的 cs id ,chunk type id酥艳,以及 data 的長(zhǎng)度和時(shí)間戳的差值都相同摊溶,因此采用 類型 3,省去全部的 Message Header 的信息充石;
    -2. 因此占用 33 = 1 + 32
  • 分析第四個(gè)chunk:
    -1.第四個(gè) chunk 和第三個(gè) chunk 情況相同莫换,也占用 33 = 1 + 32 個(gè)字節(jié)。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惫企,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子陵叽,更是在濱河造成了極大的恐慌狞尔,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巩掺,死亡現(xiàn)場(chǎng)離奇詭異偏序,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锌半,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門禽车,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人刊殉,你說我怎么就攤上這事殉摔。” “怎么了记焊?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵逸月,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我遍膜,道長(zhǎng)碗硬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任瓢颅,我火速辦了婚禮恩尾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挽懦。我一直安慰自己翰意,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布信柿。 她就那樣靜靜地躺著冀偶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪渔嚷。 梳的紋絲不亂的頭發(fā)上进鸠,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音形病,去河邊找鬼客年。 笑死霞幅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搀罢。 我是一名探鬼主播蝗岖,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼榔至!你這毒婦竟也來了抵赢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤唧取,失蹤者是張志新(化名)和其女友劉穎铅鲤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枫弟,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邢享,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淡诗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骇塘。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖韩容,靈堂內(nèi)的尸體忽然破棺而出款违,到底是詐尸還是另有隱情,我是刑警寧澤群凶,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布插爹,位于F島的核電站,受9級(jí)特大地震影響请梢,放射性物質(zhì)發(fā)生泄漏赠尾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一毅弧、第九天 我趴在偏房一處隱蔽的房頂上張望气嫁。 院中可真熱鬧,春花似錦够坐、人聲如沸寸宵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嘶朱,卻和暖如春蛾坯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疏遏。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工脉课, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留救军,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓倘零,卻偏偏與公主長(zhǎng)得像唱遭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呈驶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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

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