流媒體傳輸協議之 RTP(下篇)

本系列文章將整理各個流媒體傳輸協議,包括 RTP/RTCP,RTMP,但願經過深刻梳理協議的設計細節,可以給流媒體領域的開發者帶來必定的啓發。html

做者:逸殊
審覈:泰一算法

接上篇:《 流媒體傳輸協議之 RTP(上篇)》安全

RTP 控制協議

Sender & Receiver 報告

RTP 使用 Sender 報告(SR)和 Receiver 報告(RR)來反饋數據的接收質量,若是是媒體數據的發送者那就會發送 SR,不然發送 RR。這兩類報文是經過頭部的報文類型識別碼來作區分的。SR 相對於 RR 來講多了 20byte 的 Sender 相關信息,除此以外其餘內容都是同樣的。網絡

SR 報文

流媒體傳輸協議之 RTP(下篇)

SR 報文包含三個部分,第一個部分是頭部,有 8 BYTE,各個字段的含義以下:app

  • version (V): 2 bits,RTP 協議版本。
  • padding (P): 1 bit,是否包含填充,最後一個填充字節標識了總共須要忽略多少個填充字節(包括本身)。Padding 可能會被一些加密算法使用,由於有些加密算法須要定長的數據塊。在複合包中,只有最後一個 RTCP 包須要添加填充。
  • reception report count (RC): 5 bits,有多少個接收報告。能夠爲 0。
  • packet type (PT): 8 bits,200 表示 SR 報文。
  • length: 16 bits,報文長度(按 32-bit 字統計),包含頭部和填充字節。
  • ***C: 32 bits,身份定位符。

第二部分是發送者信息,包含 20 BYTE 的數據,總結了這個發送的的傳輸統計,各個字段的含義以下:ide

  • NTP timestamp: 64 bits,Wallclock time,用於計算 RTT。
  • RTP timestamp: 32 bits,RTP 時間戳,基於 NTP 的某一隨機偏移量。用於媒體數據內同步。
  • sender's packet count: 32 bits,這個 ***C 總共發送了多少包。
  • sender's octet count: 32 bits,這個 ***C 總共發送了多少 BYTE 的數據。

第三部分可能什麼都沒有,也可能有多個接收報告,這取決的上次報告之後收到了多少個 Sender 的數據。每一個報告塊統計了一個 ***C 的包數。具體內容以下:函數

  • ***C_n (source identifier): 32 bits,這個信息塊對應的 ***C。
  • fraction lost: 8 bits,上次 SR 或 RR 發送後到目前爲止的丟包率。
  • cumulative number of packets lost: 24 bits,總體過程的丟包總數。
  • extended highest sequence number received: 32 bits,低 16-bit 是收到的最新的 RTP 報文序列號,高 16-bit 是序列號循環的次數。
  • interarrival jitter: 32 bits,RTP 數據報文抵達時間的抖動。若是 Si 表明 i 包中包含的 RTP 時間戳,Ri 表明 i 包被接收時的 RTP 時間戳,那兩個包 i 和 j 的到達時間抖動算法以下::D(i,j) = (Rj - Ri) - (Sj - Si) = (Rj - Sj) - (Ri - Si)。咱們在計算這個抖動時,要結合每一個包的抖動,來計算一個平均值,計算平均值的方案以下:J(i) = J(i-1) * (15 / 16) + (|D(i-1,i)|)/16。
  • last SR timestamp (LSR): 32 bits,該 ***C 最後一個 RTCP 報文(SR)中帶的 NTP 時間。
  • delay since last SR (DLSR): 32 bits,從該 S*** 最後一個 RTCP 報文(SR)被收到以來通過的時間。

數據的發送者能夠經過當前時間 A,接收到 RR 部分中的 LSR 和 DLSR 來計算 RTT,計算示意圖以下:
流媒體傳輸協議之 RTP(下篇)工具

RR 報文

流媒體傳輸協議之 RTP(下篇)

接收報告的格式和發送報文格式同樣,只不過它在頭部中用 201 表示這是一個 RR 報文。此外 RR 報文中不含有上述 SR 報文中的第二部分。若是 RR 報文是空的那麼須要在頭部標明 RC=0。oop

發送 / 接收報文的拓展
一些預設可能根據本身的需求,要在接收報告和發送報告中附加一些信息。那麼這些附加內容應該在 SR 或者 RR 的結尾以後。若是這些內容只有發送者相關,那麼 RR 中就不包含這些信息。測試

分析發送報告和接收報告
這些接收質量的報告信息可能不光只有發送者要使用,接收者或者第三方監控器也會使用。發送者可能根據接收質量調整本身的傳輸策略。接收者能夠根據這個信息來肯定本身遇到的問題是本地網絡的問題仍是整個 Session 的問題。網絡的管理者能夠根據這些信息來評估整個網絡環境的狀況。

SDES 報文

流媒體傳輸協議之 RTP(下篇)
SDES 是一個三級結構,它包含一個頭和 0 個或多個數據塊,每個數據塊對應了一個 ***C 或 CSRC,它又由多個描述字段組成。頭部的信息以下:

  • version (V),padding (P),length: 和上面同樣。
  • packet type (PT): 8 bits,202 表示 SDES 類型。
  • source count (SC): 5 bits,***C/CSRC 塊的數量。

每個塊中都包含多個描述內容,這些描述內容都是 32-bit 對齊的,其中前 8-bit 描述了類型,接着 8-bit 描述了信息長度(不包含前 16-bit),而後信息內容。注意信息部分不能超過 255 BYTE,這和前面的不少工做相似是爲了約束 RTCP 的帶寬。

描述的文本內容是 UTF-8 編碼的。若是要使用多字節的編碼,須要在醒目的地方表示用的什麼的編碼。

各個描述部分是沒有中間分隔的,因此要用空字節來填充以達到對齊的效果。注意這裏的填充和 RTCP 頭部的 P 不是一個概念。

末端節點發送的 SDES 包含他本身的數據源標識。而 Mixer 發送的 SDES 包含多個 CSRC,若是 CSRC 的數量超過了 31 個,會拆分紅多個 SDES 報文。

SDES 的全部類型會在後面一一介紹。其中只有 CNAME 是強制要有的。可能有一些類型的的描述只有部分預設纔會使用。可是這些內容都是在一個共通的地方來記載,以防止不一樣的預設使用的描述類型發生衝突。若是要註冊新的類型,須要經過 IANA 註冊。

CNAME:權威的末端節點身份標識

流媒體傳輸協議之 RTP(下篇)
CNAME 有以下特徵:

  • 由於 ***C 在許多意外狀況下會從新生成,因此 CNAME 被用來綁定舊的 ***C 和新的 ***C,來保持數據源的連續。
  • 和 ***C 同樣,CNAME 也須要保證惟一性(同一個 Session 中)。
  • 爲了讓同一個參與者的多個 ***C 綁定在一塊兒,咱們須要 CNAME 是固定的。
  • 爲了讓第三方監控用起來方便,CNAME 應該即方便程序使用,也要設計成可讀的,能夠根據它確認來源。

所以 CNAME 應該經過算法來生成而不是手動生成。爲了知足如上須要,通常來講是按照以下的格式來描述 CNAME:

  • "user@host" eg: "doe@192.0.2.89" or "doe@2201:056D::112E:144A:1E24".
  • "host", 若是是單用戶系統,獲取不到 user 時只使用 host。eg: "sleepy.example.com","192.0.2.89" or "2201:056D::112E:144A:1E24".

有些人可能會發現,若是上述的 host 使用的是子網地址的話,就沒辦法保證整個 Session 的惟一性了,一般這類沒有直接 IP 的使用者是經過一個 RTP 級別的 Translator 來訪問公共網絡。這個 Translator 會處理從私有地址到公網地址的轉換工做。

NAME:用戶名

流媒體傳輸協議之 RTP(下篇)

這個是描述數據源的真實名字,eg:"John Doe, Bit Recycler"。整個 Session 過程當中但願這個值不變。全 Session 不須要惟一。

EMAIL:電子郵箱地址

流媒體傳輸協議之 RTP(下篇)

電子郵箱地址,eg: "John.Doe@example.com"。整個 Session 過程當中但願這個值不變。

PHONE:電話號碼

流媒體傳輸協議之 RTP(下篇)

電話號碼須要以國際訪問碼開頭,eg: "+1 908 555 1212"。

LOC:用戶地理地址

流媒體傳輸協議之 RTP(下篇)

視應用不一樣,詳細程度會各不相同。

TOOL:應用名或工具名

流媒體傳輸協議之 RTP(下篇)

帶版本號的應用名,能夠用來 DEBUG。

NOTE:提醒 / 狀態

流媒體傳輸協議之 RTP(下篇)

用來發送暫時性的消息描述當前狀態。eg: "on the phone, can't talk"。

PRIV:自定義拓展

流媒體傳輸協議之 RTP(下篇)

上層應用自定義的格式。通常都是用過一個前綴描述消息類型,而後後面跟着消息正文。

BYE 報文

流媒體傳輸協議之 RTP(下篇)

BYE 報文表示一個或多個流媒體源再也不活躍。

  • version (V),padding (P),length: 同上。
  • packet type (PT): 8 bits,203 表示 BYE 報文。
  • source count (SC): 5 bits,退出 Session 的 ***C 的數量。

若是 BYE 報文被 Mixer 收到了,Mixer 應該啥都不改動,就發給下一節點。若是 Mixer 關閉了,它要發送一個包含它管理的全部 ***C 的 BYE 報文。BYE 報文中可能也會跟着帶一些離開緣由的描述。這些描述和 SDES 中帶的描述相似,須要 32-bit,用空字節填補空缺。

APP:應用定義的 RTCP 報文

流媒體傳輸協議之 RTP(下篇)

APP 報文通常用於實驗性的功能和開發。若是識別到了不認識 NAME 那麼上層應用通常都會忽略它。若是開發或者測試功能穩定了,通常是要經過 IANA 註冊一個新的 RTCP 報文類型。

  • version (V),padding (P),length: 同上。
  • subtype: 5 bits,APP 報文子類型,通常是上層應用定義。
  • packet type (PT): 8 bits,204 表示 APP 類型的 RTCP 報文。
  • name: 4 octets 通常是應用名,防止 subtype 衝突。
  • application-dependent data: variable length 和上層應用相關的內容,須要 32-bit 對齊。

RTP Translator & Mixer

做爲末端節點的補充,RTP 引入了 Translator 和 Mixer 的概念,它們是 RTP 層的中間件。雖然這多少增長了協議的複雜度,可是對音視頻通話應用來講它們仍是很關鍵的,由於它們能解決防火牆問題和低帶寬鏈接的問題。

描述

一個 RTP Translator/Mixer 鏈接至少兩個傳輸層的用戶組。一般來講,這裏提到的用戶組是公共網絡的概念,傳輸層協議會爲其生成一個組播地址(ip:port)。網絡層協議,像是 IPv4 和 IPv6 對 RTP 協議來講是隱藏的。一個系統可能會有多個 Translator 和 Mixer(多個 Session),它們中的每個均可以看做是一個用戶組的邏輯分割。

爲了不建立在建立 Translator 和 Mixer 形成了網絡包循環,必須遵循下列規則:

  • 每一個經過鏈接 Translator 和 Mixer 而加入 Session 的用戶組,要麼須要網絡層隔離,要麼最少互相知道這些參數(protocol,address,port)中的一個。
  • 由上一個規則推廣的話,各個用戶組絕對不能同時鏈接多個 Translator 或者 Mixer,除非有某種機制能保證他們之間數據被阻斷。

Translator:在不改變 RTP 報文 ***C 的條件下,向後傳播該報文,正由於如此,報文的接收者才能識別到 Translator 轉發後的報文究竟是來自哪一個人。有些 Translator 可能直接轉發報文,不作任何改動,也有可能改變數據編碼,payload 類型和時間戳。

若是多個數據報文被從新編碼併合併到一塊兒的話,Translator 必須爲這類報文指定一個組新的序列號。這樣,輸入報文的丟失就會致使輸出報文的斷層。數據的接收者通常是不知道 Translator 的存在的,除非經過 payload 類型的不一樣或者傳輸層報文的源地址來判斷。

Mixer:從一個或多個數據源那裏接收數據,隨後可能會改變數據的格式,而後將這些數據合併,並傳遞給下家。由於多個數據源的時序並不必定是同步的,因此 Mixer 須要整合各個數據源的時序關係,並將其映射到本身的一套時序上,因此 Mixer 也是一個 ***C,全部經過 Mixer 的報文必須打上該 Mixer 的 ***C。

爲了表示這些數據的原始數據源,通常會經過 CSRC 列表來記錄。有些 Mixer 可能本身也是一個原始數據源,因此他本身的 ***C 也會出如今 CSRC 列表中。有些應用可能不但願 Mixer 的 ***C 出如今 CSRC 中,可是這樣可能就沒法發現循環網絡包。

流媒體傳輸協議之 RTP(下篇)

上圖是一個 Mixers 和 Translators 鏈接的例子。[] 表明末端節點,() 表明 Mixer,<> 表明 Translator,"M1:48 (1, 17)" 表示 Mixer1 的報文,48 是 Mixer1 的 ***C,括號裏的 1,17 是 CSRC,它合併了 E1:17 和 E2:1 這兩個節點的數據。

Translator 處理 RTCP

除了要轉發數據包,進行數據包的更改,Translator 和 Mixer 也要發送 RTCP 報文。在不少狀況下,它會將收到的末端節點的 RTCP 報文合併到複合包中。當再次收到這些包時或者本身的 RTCP 週期到時,它會將複合包發送出去。

有的 Translator 可能對收到的 RTCP 報文不作任何改動,只是簡單的轉發這個包。若是這個 Translator 改變了報文數據的 payload,它必須對 SR 或者 RR 作相關的改動。一般來講,Translator 不能將多個數據源的 SR 和 RR 合併,由於這樣會致使 RTT 的計算出現問題(RTT 根據 LSR 和 DLSR 計算)。

  • SR 中的發送者信息: Translator 不會建立本身的發送者信息,它會將收到 SR 傳給下家。其中 ***C 不會發生任何改動,可是發送者信息有必要的話必定要作適當的改動。若是 Translator 改變了數據編碼,那 "byte count" 字段就要更改。若是他將多個數據報文合併,那它須要修改 "sender's packet count" 字段。若是它改變了時間頻率,那就須要修改 "RTP timestamp"。
  • SR/RR 中的接收者信息:***C 不會發生任何改動,若是 Translator 改變了序列號,那就須要修改 "extended last sequence number",在某些極端狀況下,它可能徹底沒有接收反饋,或者根據接收到的 SR/RR 來構建本身的接收報告。通常狀況下 Translator 是不須要本身的 ***C 的,可是若是是爲了表示本身的數據接收狀況,它可能也會生成本身的 ***C,並將這些 RTCP 報文發送過全部的鏈接者。
  • SDES:通常 Translator 收到 SDES 後會什麼都不改就發給下家,可是也有可能爲了節約帶寬篩掉 CNAME 以外的信息的,若是 Translator 要發送本身的 RR 信息,那它必定要發送一個本身的 SDES 給全部鏈接者。
  • BYE:無改動轉發,若是 Translator 有本身的 ***C 也要發送本身的 BYE。
  • APP:無改動轉發。

Mixer 處理 RTCP

由於 Mixer 會生成本身的數據流,因此他不會轉發通過他的 SR 和 RR 而是爲鏈接雙方發送本身的 SR 和 RR 報文。

  • SR 的發送者信息:Mixer 不轉發數據來源的發送信息。它會生成本身的發送者信息並把它發送給下家。
  • SR/RR 中的接收者信息:Mixer 會生成本身的接收信息,而後發送給全部數據來源,它絕對不能作接收報告的轉發工做,或者把本身的接收信息發給錯誤的對象。
  • SDES:Mixers 一般會不作任何改動就轉發 SDES 信息,可是也有可能爲了節約帶寬過濾除了 CNAME 以外的其餘信息。Mixer 必須發送本身的 SDES 報文。一般,Mixer 會將多個收到的 SDES 打包一塊兒發送。
  • BYE:Mixer 必須轉發 BYE 報文。若是 Mixer 要退出時,它會將全部數據來源的 ***C 放進 BYE 報文,也包括本身的 ***C。
  • APP:視上層應用。

瀑布型 Mixer

一個 RTP Session 可能包含多個 Mixer 和 Translator,就像上圖同樣。若是 Mixer 是瀑布型的,就像 M2 和 M3,一個 Mixer 收到的數據多是已經合併過的,它有本身的 CSRC 列表。那麼第二個 Mixer 須要將以前的 CSRC 和本身接收的全部 ***C 合併。就像圖中 M3 的輸出是 M3:89 (64,45)。

***C 的分配和使用

前面已經說過 ***C 是一個隨機的 32-bit 數,它須要在整個 Session 內保證惟一性。因此同一個網絡下的參與者在剛加入 Session 時使用不一樣的 ***C 相當重要。

咱們不能簡單的用本地的網絡地址,由於可能不惟一。也不能不考慮初始狀態而簡單地調一個隨機數函數。

碰撞的可能性

由於 ***C 是隨機選擇的,這就可能多個數據源選用了相同的 ***C。若是你們是同時加入 Session 的話,這個碰撞的概率就更高。若是 ***C 的數量是 N,L 是 ***C 的數據長度(這裏是 32),那麼碰撞的可能性是 1 - exp(-N2 / 2(L+1)),當 N=1000 時,碰撞率大概是 10**-4。

一般來講,實際的碰撞率會比上述的最壞狀況要低。一般一個新節點加入時,其餘節點已經有了本身的惟一 ***C,這時候碰撞的機率只是生成的新 ***C 在這些現有 ***C 之中的可能性。這時候碰撞率是 N/2**L。當 N=1000 時,碰撞率大約是 2*10**-7。

由於新加入的節點會先接收一段時間的報文而後才發送本身的第一個報文,因此在它生成 ***C 時能夠避開已知的 ***C,這也有效的下降了碰撞的概率。

碰撞的解決方案和循環的發現

一般來講 ***C 碰撞的可能性很小,全部的 RTP 實現必須有發現衝突的機制,並在發現衝突時做出適當的處理。若是數據源發現了任何一個別的數據源和本身使用同一個 ***C,它必須用原來的 ***C 發送一個 BYE 報文,而後選用一個新的 ***C。若是一個數據的接收者發現了多個數據源的 ***C 碰撞了(經過傳輸地址或者 CNAME),那麼它會只接收其中一我的的報文,丟棄另外一我的的全部報文。

由於整個 Session 中的 ***C 是惟一的,因此它也能夠被用來發現環型報文。環形報文會致使數據的重複以及控制信息的重複。

  • Translator 可能會錯誤地將報文發送回該報文來的地方。
  • 兩個 Translator 錯誤地同時啓動,它們兩個都會轉發一樣的數據。
  • Mixer 可能會錯誤地將合併報文發送回這些報文來的地方。

一個數據源可能發現本身的或者別人的報文被循環發送了。不管是報文循環仍是 ***C 的碰撞都會致使同一個現象,即 ***C 相同可是傳輸地址不一樣的報文。所以,若是數據源改變了本身的傳輸地址,那它就須要同時改變本身的 ***C 來避免被檢測成環形報文。有一個須要注意的內容是,若是一個 Translator 再重啓的過程當中改變了本身的傳輸地址,那麼這個 Translator 轉發的全部數據都會被檢測成環。這類狀況的解決方案通常有以下兩個:

  • 重啓的時候不改變傳輸地址。
  • 接收者的超時機制。

若是循環或者碰撞發生在離 Translator 和 Mixer 很遠的地方,咱們就不能經過傳輸地址來發現。可是咱們仍然能夠經過 CNAME 的不一樣來發現 ***C 碰撞。

爲了解決上述問題,RTP 的實現必須包含一個相似以下的算法。這個算法不包括多個數據源 ***C 碰撞的狀況,這類狀況一般下都是先用原來的 ***C 發送一個 BYE 而後從新選擇一個新的 ***C。

這個算法須要維護一個 ***C 和傳輸地址的映射關係。由於 RTP 的數據和 RTCP 傳輸使用的是兩個不一樣的端口,因此一個 ***C 對應的是兩個傳輸地址。

每次收到 RTP 報文和 RTCP 報文都會將其 ***C 和 CSRC 在上述的表中進行比對。若是發現了傳輸地址對不上的狀況,咱們就能夠說發現了一個循環或者碰撞。對於 RTCP 數據來講,可能每一個數據塊都有本身獨立的 ***C,好比 SDES 數據,對於這種狀況就須要分別比對。若是沒有在表中找到這個 ***C 或者 CSRC,就須要新添加一項。當收到 BYE 報文時,須要先比對這個 BYE 的傳輸地址,若是傳輸地址匹配上了,就將這一項從表中刪除。或者基於超時機制,將超時的數據從表中移除。

爲了追蹤本身的數據報文循環狀況,必須維護另外一個列表,這個表存儲衝突報文的傳輸地址和收到該報文的時間。若是超過 10 個 RTCP 週期都沒有收到這個傳輸地址的衝突報文,就將該項從表中刪除。

下面的算法還假設參與者本身的 ***C 和狀態都包含在 ***C 表中,它會先比對本身的 ***C。

if (***C or CSRC identifier is not found in the source
             identifier table) {
             create a new entry storing the data or control source
                 transport address, the ***C or CSRC and other state;
         }
   /* Identifier is found in the table */
   else if (table entry was created on receipt of a control packet
            and this is the first data packet or vice versa) {
       store the source transport address from this packet;
   }
   else if (source transport address from the packet does not match
            the one saved in the table entry for this identifier) {
       /* An identifier collision or a loop is indicated */
       if (source identifier is not the participant's own) {
           /* OPTIONAL error counter step */
           if (source identifier is from an RTCP SDES chunk
               containing a CNAME item that differs from the CNAME
               in the table entry) {
               count a third-party collision;
           } else {
               count a third-party loop;
           }
           abort processing of data packet or control element;
           /* MAY choose a different policy to keep new source */
       }
       /* A collision or loop of the participant's own packets */
       else if (source transport address is found in the list of
                conflicting data or control source transport
                addresses) {
           /* OPTIONAL error counter step */
           if (source identifier is not from an RTCP SDES chunk
               containing a CNAME item or CNAME is the
               participant's own) {
               count occurrence of own traffic looped;
           }
           mark current time in conflicting address list entry;
           abort processing of data packet or control element;
       }
       /* New collision, change ***C identifier */
       else {
           log occurrence of a collision;
           create a new entry in the conflicting data or control
               source transport address list and mark current time;
           send an RTCP BYE packet with the old ***C identifier;
           choose a new ***C identifier;
           create a new entry in the source identifier table with
               the old ***C plus the source transport address from
               the data or control packet being processed;
       }
   }

層級編碼

對於不一樣 Session 的層級編碼傳輸,通常都是全部層都使用同一個 ***C,若是其中某一層發現了 ***C 衝突,那麼只改變這一層的 ***C,並且他層的 ***C 不作改變。

安全

下層協議可能會提供 RTP 應用所須要的全部安全服務,包括認證,數據完整性,數據保密性。這些服務在 IP 協議中都有解決方案。由於 Audio 和 Video 初始化過程當中須要數據加密,而這時候 IP 協議這一層的安全服務尚未提供。因此,RTP 須要實現一個 RTP 專用的保密服務。這個保密服務是很是輕量級的,並且保密部分的服務向後兼容,之後能夠隨時進行更換。或者,某些預設會提供這部分加密服務,好比 SRTP(Secure Real-time Transport Protocol),SRTP 是基於 Advanced Encryption Standard (AES) 提供了一個比 RTP 默認加密服務更強大的實現。

保密性

保密性是指咱們的報文只但願一些特定的接收者能夠解碼成明文,而其餘人只能獲得無用的信息,保密性是經過加密編碼來提供的。

當須要爲 RTP 和 RTCP 報文提供加密服務時,全部傳輸的內容都會在下層報文那裏進行加密。對於 RTCP 來講,須要一個 32-bit 的隨機數做爲前綴。而 RTP 報文不須要前綴,取而代之的是隨機序列號和時間戳偏移。由於隨機部分不多,因此能夠說這是一個很是弱的初始向量。此外,***C 也可被破解者修改,這是這個加密方案的另外一個薄弱的環節。

對於 RTCP 來講,可能會將一個複合包分紅兩批,第一批加密,後一批明文發送。例如,SDES 部分的信息可能加密,而接收報告部分不加密就發送出去,由於只有這樣那些第三方監控器才能在不知道密鑰的狀況下統計網絡情況。以下圖所示,SDES 信息必須跟在一個空的 RR 後,而且要有一個隨機前綴。

RTP 協議使用的 Data Encryption Standard (DES) 算法,使用 cipher block chaining (CBC) 模式,這須要數據填充到 64-bit 對齊。密碼算法使用零做爲初始向量,由於 RTCP 報文中已經有一個隨機前綴了。

流媒體傳輸協議之 RTP(下篇)

RTP 之因此選擇這個默認協議是由於它用起來很容易,可是由於 DES 太容易破解了。因此推薦預設中使用更健壯的加密算法來替換這個默認方案,例如 Triple-DES。這些算法廣泛須要一個隨機初始化塊,RTCP 使用了 32-bit 的隨機數做爲前綴,RTP 使用了時間戳和序列號的隨機偏移,但是相鄰的 RTP 報文之間的隨機性就不好。須要注意的是,不管是 RTCP 仍是 RTP,它們的隨機性都有限。加密型更好的應用,須要考慮更多的保密措施。例如 SRTP 配置文件,就基於 AES 來加密,它的加密方案就更完備,選擇這個預設來使用 RTP 就挺不錯的。

前面提到過也能夠用 IP 級的加密方案或者 RTP 級的加密,一些預設可能會定義別的 payload 類型來加密。這種方案,可能只加密 payload 部分而頭部分使用明文,由於只有 payload 部分纔是應用真正須要的內容。這可能對硬件設備來講很是有用,它既處理解密過程,又處理解碼過程。

身份認證和消息完整性

RTP 協議這一層沒有身份認證和消息完整性服務,由於有些上層服務可能沒有認證就能使用。而消息完整性服務依賴下層協議來實現。

RTP 下的網絡層和傳輸層協議

RTP 須要下層協議提供多路複用機制。對於 UDP 這類應用,推薦 RTP 應該使用一個偶數端口傳輸數據,和它相關的 RTCP 流應該是用高一位的奇數端口。在單播模式下,每一個參與者都須要一對端口來傳輸 RTP 和 RTCP 報文。兩個參與者可能使用相同的端口。絕對不能以接收到的報文網絡地址直接做爲目標地址發送報文。

建議層編碼模式是,使用相鄰的端口,所以對於層 N 來講,數據端口是 P+2N,控制端口是 P+2N+1。對於 IP 組播來講,可能不會獲得相鄰的組播地址。

RTP 數據報文沒有描述報文長度的信息。因此 RTP 報文依賴下層協議提供長度標識。因此一個 RTP 報文的最大長度由下層協議限制。

若是 RTP 報文使用的下層協議是流傳輸協議的話,必須定義一套數據幀分割機制。

參考

[1] rfc3550

閱讀做者的更多文章,關注做者我的公衆號:貝貝貓技術分享

做者的我的博客:https://www.beikejiedeliulangmao.top/

「視頻雲技術」你最值得關注的音視頻技術公衆號,每週推送來自阿里雲一線的實踐技術文章,在這裏與音視頻領域一流工程師交流切磋。

相關文章
相關標籤/搜索