.引言
本篇文章也涉及到很多知識(shí)點(diǎn),如果對(duì)于細(xì)節(jié)部分不是很了解,可以閱讀前面的文章,能夠幫助你更加理解本篇文章。通過(guò)系列文章來(lái)講解,本篇文章是第一篇。參考文章內(nèi)容列表如下:
SRS流媒體框架分析(1)
SRS流媒體之RTMP拉流框架分析(4)
SRS流媒體之RTMP拉流框架分析(3)
SRS流媒體之RTMP推流框架分析(2)
簡(jiǎn)述SRS流媒體服務(wù)器相關(guān)技術(shù)
SRS流媒體服務(wù)器集群之Forward模式(2)
SRS流媒體服務(wù)器集群之Forward模式(1)
SRS流媒體服務(wù)器之HLS源碼分析(2)
SRS流媒體服務(wù)器之HLS源碼分析(4)
SRS流媒體服務(wù)器之RTMP協(xié)議分析(2)
SRS流媒體服務(wù)器之HLS源碼分析(3)
SRS流媒體服務(wù)器之HLS配置、測(cè)試和技術(shù)選型
SRS流媒體服務(wù)器之HLS源碼分析(1)
SRS流媒體服務(wù)器之RTMP協(xié)議分析(1)
SRS流媒體服務(wù)器之RTMP推流消息處理(1)
SRS流媒體服務(wù)器之HTTP-FLV框架分析(1)
SRS流媒體服務(wù)器集群之Edge模式(1)
SRS流媒體服務(wù)器集群之Edge模式(2)
SRS流媒體服務(wù)器之HTTP-FLV框架分析(2)
SRS流媒體服務(wù)器集群之Edge模式(3)
SRS流媒體服務(wù)器之HTTP-FLV框架分析(2)
手把手配置HLS流媒體服務(wù)器
詳解Nginx系列
Nginx架構(gòu)與Handler模塊最詳分析(2)
Nginx架構(gòu)與Handler模塊最詳分析(3)
Nginx架構(gòu)與Handler模塊最詳分析(1)
Nginx 源碼分析之 Filter 模塊(1)
Nginx 源碼分析之 Upstream 模塊(1)
流媒體推拉流實(shí)戰(zhàn)之RTMP協(xié)議分析(BAT面試官推薦)
超詳細(xì)RTMP協(xié)議詳解(資深流媒體架構(gòu)師推薦)
RTP協(xié)議
RTP之AAC框架分析
詳解RTP打包AAC實(shí)戰(zhàn)分析(1)
詳解RTP封包和拆包AAC實(shí)戰(zhàn)分析(2)
詳解RTP打包AAC實(shí)戰(zhàn)分析(1)
詳解RTP協(xié)議之H264封包細(xì)節(jié)(1)
詳解RTP協(xié)議之H264封包和解包實(shí)戰(zhàn)
詳解RTCP協(xié)議和源碼分析
1.視頻會(huì)議系統(tǒng)行業(yè)簡(jiǎn)述
視頻會(huì)議系統(tǒng)(Video Conference)是指通過(guò)因特網(wǎng)實(shí)現(xiàn)位于多個(gè)(至少兩個(gè))地點(diǎn)的人們進(jìn)行類(lèi)似于面對(duì)面交流的遠(yuǎn)程視音頻通信服務(wù)平臺(tái)。視頻會(huì)議系統(tǒng)除了支持傳統(tǒng)的文字聊天和語(yǔ)音通話功能,還集成了動(dòng)態(tài)圖像、電子白板、群組交流和視頻通話等強(qiáng)大功能。它最大化地豐富了人們?cè)谏詈凸ぷ髦薪涣鞯姆绞剑灿兄谔岣呷藗儨贤ê徒涣鞯馁|(zhì)量。
視頻會(huì)議系統(tǒng),已經(jīng)廣泛地應(yīng)用于政府部門(mén)、軍隊(duì)和大型企事業(yè)單位,還擴(kuò)展到能源、科技、醫(yī)療、金融以及教育等領(lǐng)域。近些年來(lái),隨著視頻會(huì)議應(yīng)用從傳統(tǒng)行業(yè)、大型公司轉(zhuǎn)向中小型企業(yè)、普通用戶和個(gè)人,視頻會(huì)議系統(tǒng)在國(guó)內(nèi)的市場(chǎng)規(guī)模得到不斷地發(fā)展壯大。近六年,我國(guó)視頻會(huì)議系統(tǒng)市場(chǎng)銷(xiāo)售份額(來(lái)自《2016-2022 年中國(guó)視頻會(huì)議系統(tǒng)市場(chǎng)分析報(bào)告》),如下所示:
2.Nginx 服務(wù)器簡(jiǎn)述
Nginx(engine X)是一款輕量級(jí)的 Web 服務(wù)器/反向代理服務(wù)器及電子郵件代理服務(wù)器。隨著 HTTP 核心模塊和各類(lèi) HTTP 擴(kuò)展模塊的出現(xiàn),Nginx 被更多的國(guó)內(nèi)公司用來(lái)取代 Apache 而獨(dú)立承擔(dān)起 Web 服務(wù)器,如淘寶、百度、新浪、網(wǎng)易以及騰訊等。由于 Nginx 本著“一切皆為模塊”的設(shè)計(jì)理念,活躍的社區(qū)出現(xiàn)了大量的第三方擴(kuò)展模塊,這也讓 Nginx 功能越來(lái)越強(qiáng)大。例如,Arut 開(kāi)發(fā)的 nginx-rtmp-module 模塊可以支持 RTMP 協(xié)議,使 Nginx 成為支持直播和點(diǎn)播服務(wù)的流媒體服務(wù)器。在這里我也推薦一款國(guó)內(nèi)開(kāi)源的流媒體服務(wù)器,SRS,這個(gè)支持的組件更多,功能也更好用。
W3C 聯(lián)合全球 60 多家公司,歷時(shí)八載,于 2014 年 8 月發(fā)布了 HTML5 正式標(biāo)準(zhǔn)。HTML5 標(biāo)準(zhǔn)提出了大量新特性,特別是 Web Socket 協(xié)議,一種支持服務(wù)器主動(dòng)推送消息給客戶端,非常適合構(gòu)建網(wǎng)絡(luò)直播、在線教育以及視頻會(huì)議等實(shí)時(shí) web 應(yīng)用。目前,一種新型的 HTML5 視頻會(huì)議客戶端成為研究熱點(diǎn),主要包括以下三種:基于 HLS 的HTML5 客戶端、基于 Web RTC 的 HTML5 視視客戶端(在各大主流流媒體廠商得到了廣泛應(yīng)用)和基于 Web Socket 協(xié)議、HTML5原生組件及 Java Script 的 HTML5 客戶端。
視頻會(huì)議系統(tǒng)可劃分為硬件視頻會(huì)系統(tǒng)和軟件視頻會(huì)議系統(tǒng)。大多數(shù)硬件視頻會(huì)議系統(tǒng)的廠商都是國(guó)外公司,如美國(guó)寶利通(Polycom)、挪威泰德集團(tuán)(TANDBERG)以及日本索尼(sony)等,當(dāng)然他們也推出對(duì)應(yīng)地軟件型視頻會(huì)議系統(tǒng)。國(guó)內(nèi)提供視頻會(huì)議系統(tǒng)服務(wù)的公司,主要包括華為、科達(dá)、中興以及瑞福特,騰訊,釘釘,聲網(wǎng)等,一般只提供軟件型視頻會(huì)議系統(tǒng)。
3.協(xié)議介紹與關(guān)鍵技術(shù)講解
3.1TCP
TCP(Transmission Control Protocol,傳輸控制協(xié)議)是互聯(lián)網(wǎng)傳輸層最重要的協(xié)議之一,提供端到端服務(wù)的協(xié)議。TCP 是一種面向連接的可靠傳輸協(xié)議,提供一種全雙工的通信。如下圖所示:
傳輸層還有一種非常重要的協(xié)議 UDP(User Data Protocol,用戶數(shù)據(jù)報(bào)協(xié)議),是一種非連接的盡最大努力交付的協(xié)議。UDP 和 TCP 設(shè)計(jì)機(jī)制非常不同,甚至是相對(duì)的。為了明確 TCP 的特點(diǎn),下面將 TCP 和 UDP 進(jìn)行比較。如下圖所示:
TCP 和 UDP 進(jìn)行比較
TCP 最大的優(yōu)點(diǎn)就是數(shù)據(jù)傳輸可靠。經(jīng)過(guò)三次握手機(jī)制建立連接,TCP 按順序發(fā)送數(shù)據(jù)包,接收方需要向發(fā)送方確認(rèn)數(shù)據(jù)包的信息。因此,TCP 不僅保證了數(shù)據(jù)正確性,還保證了數(shù)據(jù)順序性。目前,基于 TCP 的應(yīng)用十分廣泛,如 HTTP、FTP、SMTP、IMAP、POP3 以及 TELNET都是基于TCP。
3.2 RTP和RTCP
RTP(Real-time Transport Protocol,實(shí)時(shí)傳輸協(xié)議)和 RTCP(Real-time TransportControl Protocol,實(shí)時(shí)傳輸控制協(xié)議)是一對(duì)姊妹協(xié)議,由 IETF(The InternetEngineering Task Force )于 1996 年 1 月公布 RFC1889(現(xiàn)已更新至 RFC3550)文檔所發(fā)布。RTP 主要用于互聯(lián)網(wǎng)上音頻、圖像及視頻等多媒體實(shí)時(shí)端到端傳輸服務(wù);RTCP用于保障 RTP 傳輸?shù)?strong>服務(wù)質(zhì)量,交換控制信息。
RTP 報(bào)文(RTP 協(xié)議的報(bào)文)由頭部(RTP Header)和數(shù)據(jù)負(fù)載(Payload)組成。其中,RTP 報(bào)文的頭部結(jié)構(gòu),如下圖所示:
RTP 報(bào)文的頭部結(jié)構(gòu)
RTP Header 長(zhǎng)度是可變的,固定長(zhǎng)度為前 12 字節(jié),可選 CSRC 標(biāo)識(shí)列表僅出現(xiàn)在混合器插入情況。關(guān)于 RTP Header 說(shuō)明,如下:
(1)V:2 位,標(biāo)識(shí) RTP 協(xié)議版本號(hào),當(dāng)前協(xié)議版本號(hào)為 2。
(2)P:1 位,填充標(biāo)志位,如果 P=1,RTP 報(bào)文的尾部使用一個(gè)或多個(gè)字節(jié) 0 來(lái)填充。
(3)X:1 位,擴(kuò)展標(biāo)志位。如果 X=1,表示 RTP 報(bào)頭后跟有一個(gè)擴(kuò)展包頭字段。
(4)CC: 4 位 CSRC 計(jì)數(shù)器(CSRC count)。標(biāo)識(shí)可選字段CSRC 標(biāo)識(shí)符的個(gè)數(shù)。
(5)M: 1 位 標(biāo)記位。不同的有效載荷意義不同,可參見(jiàn)spec文檔。
(6)PT: 7 位 有效載荷類(lèi)型。說(shuō)明 RTP 報(bào)文載荷的類(lèi)型,如ACC 音頻、MPEG 視頻,便于客戶端解析。
(7)Timestamp: 4 字節(jié) 時(shí)間戳。記錄了 RTP 報(bào)文的數(shù)據(jù)負(fù)載的第一個(gè)字節(jié)(8bits)的采樣時(shí)間。接收者使用該值計(jì)算延遲(延遲抖動(dòng)),進(jìn)而控制同步。
(8)SSRC identifier: 4 字節(jié) 同步信源標(biāo)識(shí)符。該字段隨機(jī)選擇的,但是兩個(gè)同步信源在一個(gè)視頻會(huì)議中不能取相同SSRC 值。
(9)CSRC identifier: 4 字節(jié) 特約信源標(biāo)識(shí)符。CSRC 標(biāo)識(shí)由混合器插入,可以有 0-15 個(gè),個(gè)數(shù)為 CC 字段值。
RTCP 實(shí)時(shí)傳輸控制協(xié)議,用于彌補(bǔ) RTP 不保證服務(wù)質(zhì)量的不足。RTCP 為 RTP 提供服務(wù)質(zhì)量的檢測(cè)、控制與反饋、實(shí)時(shí)流間的同步以及多播中成員的標(biāo)識(shí)。當(dāng)應(yīng)用程序開(kāi)啟 RTP 會(huì)話時(shí),RTP 使用偶數(shù)端口,RTCP 則使用相鄰奇數(shù)端口。也就是說(shuō)RTP和RTCP使用的是不同的socket通道。在 RTP 會(huì)話中,每個(gè)參與者周期性地發(fā)送 RTCP 報(bào)文,包含已發(fā)送(接收)數(shù)據(jù)包、丟失數(shù)據(jù)包等統(tǒng)計(jì)信息。接收端獲取這些統(tǒng)計(jì)信息,就可以及時(shí)調(diào)整發(fā)送速率,甚至調(diào)整數(shù)據(jù)負(fù)載的類(lèi)型。正如前面文章所描述的,RTCP 數(shù)據(jù)報(bào)主要類(lèi)型SR(Sender Report,發(fā)送端報(bào)告)、RR(Receiver Report,接收者報(bào)告)、SDES(SourceDescription Items,源描述)、BYE(Goodbye,通知離開(kāi))以及 APP(Application-defined,自定義應(yīng)用)。RTCP具體的頭部和相關(guān)協(xié)議文檔,可以閱讀前面的文章。
本次舉例,使用視頻會(huì)議系統(tǒng),是使用RTP/RTCP基于TCP進(jìn)行傳輸。
3.3 RTMP
RTMP(Real Time Messaging Protocol,實(shí)時(shí)消息傳輸協(xié)議)是一種用來(lái)進(jìn)行視音頻等實(shí)時(shí)數(shù)據(jù)傳輸協(xié)議。RTMP 是一種私有協(xié)議,由 Adobe Systems 開(kāi)發(fā)專(zhuān)用于 Flash 客戶端和流媒體服務(wù)器之間實(shí)時(shí)通信。RTMP 基于傳輸層 TCP 之上,默認(rèn)端口為 1935。目前,支持 RTMP 協(xié)議的服務(wù)器有很多,如 Adobe Media Server/Red5/ Nginx/SRS。RTMP協(xié)議已經(jīng)廣泛應(yīng)用于實(shí)時(shí)直播、點(diǎn)播(VOD)以及視頻通信系統(tǒng)。
3.3.1 RTMP數(shù)據(jù)包
RTMP 不僅傳輸視音視頻數(shù)據(jù),還需要傳輸信令交互數(shù)據(jù),這些數(shù)據(jù)叫作 Message。為了接收端區(qū)分 Message,發(fā)送端必須給其加上 Header 信息,即 Message Header。Message Header 結(jié)構(gòu),如下圖所示:
Message Header 結(jié)構(gòu)
(1)Message Header 總共包括四個(gè)字段,字段說(shuō)明如下:
(2)Message Type ID: 1 字節(jié) 消息類(lèi)型。1-7 用于協(xié)議控制,8 用于音頻數(shù)據(jù),9 用于視頻數(shù)據(jù),15-20 用于 AMF 命令。
(3)Message Length: 3字節(jié)消息長(zhǎng)度。表示消息中數(shù)據(jù)負(fù)載的長(zhǎng)度大小。
(4)Time Stamp: 4字節(jié)時(shí)間戳。采用絕對(duì)時(shí)間。
(5)Stream ID: 3字節(jié)媒體流 ID。標(biāo)識(shí)消息所屬媒體流ID。
對(duì)表中 Message Type ID 解釋如下:RTMP 總共定義了十多種消息類(lèi)型(具體可以參考spec文檔),每一種類(lèi)型具有指定的 ID。下面重點(diǎn)說(shuō)明三種消息類(lèi)型:
(6)Message Type ID 為 4 表示 UCM(User Control Messages,用戶控制消息),如 StreamBegin、Stream End。
(7)Message Type ID 為 18 表示 AMF0 元數(shù)據(jù)消息。AMF(Action Message Format,動(dòng)態(tài)信息格式)數(shù)據(jù)是一種與 Flash服務(wù)器高效交互的二進(jìn)制編碼數(shù)據(jù),如 00 表示 Double、02 表示 String。AMF 數(shù)據(jù)包括 AMF0、AMF3。
(8)Message Type ID 為 20 表示 RPC(Remote Procedure Call,遠(yuǎn)程過(guò)程調(diào)用)命令消息,主要分為 Net Connection 和 Net Stream 兩大類(lèi)型。前者包括 connect、call、close 與create Stream 命令;后者包括 play、publish、seek 與 pause 命令。
Message 很可能非常大,比如視頻數(shù)據(jù),由于網(wǎng)絡(luò) IP 層傳輸數(shù)據(jù)長(zhǎng)度有限(以太網(wǎng)規(guī)定 MTU 為 1500 字節(jié)),Message 往往需要分片。RTMP 將分片得到的小的數(shù)據(jù)包叫作 Chunk,又稱(chēng)“RTMP 數(shù)據(jù)包”,為了標(biāo)識(shí)每個(gè) Chunk,我們也需要給其添加頭部信息,即 Chunk Header。RTMP 數(shù)據(jù)包如下圖所示:
RTMP 數(shù)據(jù)包
Chunk Header 包括三部分:標(biāo)識(shí)本 Chunk 的 Chunk Basic Header,標(biāo)識(shí)本 Chunk 所屬 Message 的 Chunk Message Header,可擴(kuò)展的 Extended Timestamp。
(9)Chunk Basic Header(1 字節(jié)):由 Header Type 與 Channel ID 組成。Header Type 占2bit,決定頭部長(zhǎng)度,00-11 分別與 12、8、4、1byte(s)相對(duì)應(yīng)。Channel ID 用于標(biāo)識(shí)通道類(lèi)型,如下所示:
02: Ping 和 Byte Read 通道
03: Invoke 通道
04: Audio 和 Vidio 通道
05 06 07 :服務(wù)器保留
(10)Chunk Message Header(可變長(zhǎng)度):之前說(shuō)過(guò) Message Header 長(zhǎng)度為 11bytes,包含 4 個(gè)字段。Chunk Message Header 重新排列了這 4 個(gè)字段:Time Stamp、MessageLength、Message Type ID、Stream ID。當(dāng) Message 分片為 同屬于一個(gè)Message的Chunk 時(shí)候,會(huì)依次壓縮掉相同的字段(Message Length、Message Type ID 組合在一起),分別得到 11、7、3、0byte(s)情況。具體的解釋?zhuān)梢钥纯辞懊娴奈恼拢斀釸TMP。
(11)Extended Timestamp(4 字節(jié)):只有時(shí)間戳溢出時(shí)才出現(xiàn)的該字段,一般可忽略該字段部分。
因此,Message 是 RTMP 視音頻流傳輸?shù)?strong>邏輯方式,Chunk是RTMP 視音頻流傳輸?shù)膶?shí)際方式。用戶發(fā)送的數(shù)據(jù)流成為 Message 有效載荷(Message Body),被分割成固定大小的 Chunk,接著傳給下層 TCP 發(fā)送出去。
3.3.2 RTMP交互
RTMP 將數(shù)據(jù)按類(lèi)型分割成一個(gè)個(gè)固定長(zhǎng)度的數(shù)據(jù)包(Chunk)。視頻數(shù)據(jù)包默認(rèn)包體大小是 128bytes,音頻包體默認(rèn)大小是 64bytes。對(duì)于傳輸音頻/視頻數(shù)據(jù),RTMP協(xié)議既可以采用非常流行的 FLV 封裝格式封裝數(shù)據(jù)(視頻為 H264 格式,音頻為 AAC 格式),又可以采用默認(rèn)的由 Adobe 公司開(kāi)發(fā)的 AMF格式。
在傳輸 RTMP 數(shù)據(jù)包之前,必須通過(guò) RTMP 握手機(jī)制建立 RTMP 連接。連接建立成功之后,我們可以基于 RTMP 連接按照指定格式傳輸視音頻數(shù)據(jù)。這些過(guò)程,構(gòu)成了RTMP 交互過(guò)程,整個(gè)交互的過(guò)程在前面的文章也有通過(guò)wireshark抓包分析過(guò),可以參考。
(1)握手過(guò)程。
RTMP 連接從握手開(kāi)始,規(guī)范規(guī)定握手使用三組固定大小的塊組成。發(fā)起 RTMP 連接的一方(客戶端)發(fā)送的塊記作 c0,c1 和 c2,接收連接的另一方(服務(wù)器)發(fā)送的塊記作 s0,s1 和 s2。客戶端首先發(fā)送 c0 和 c1 塊;客戶端必須在接收到 s1 后才能發(fā)送 c2;客戶端發(fā)送任何 RTMP 包數(shù)據(jù)必須等收到 s2 之后。
服務(wù)器端在接收 c0 之后,才可以發(fā)送 s0 和 s1;服務(wù)器必須在接收到 c1 之后才能發(fā)送 s2;服務(wù)器發(fā)送任何 RTMP 包數(shù)據(jù)必須等到收到 c2 之后。以上的規(guī)定就是 RTMP 握手協(xié)議內(nèi)容,通過(guò)該協(xié)議客戶端就和服務(wù)器之間建立了 RTMP 連接,RTMP鏈接一般是4次握手,進(jìn)而可以相互傳輸數(shù)據(jù)。
(2)建立連接。經(jīng)過(guò)握手機(jī)制之后,客戶端與服務(wù)器可以互相發(fā)送 RTMP 數(shù)據(jù)包。RTMP協(xié)議規(guī)定,傳輸與播放媒體流需要先建立網(wǎng)絡(luò)連接(Net Connection)事件,也就是connect 過(guò)程。客戶端先發(fā)送 connect 事件到服務(wù)器,如果服務(wù)器擁有足夠資源進(jìn)行處理就會(huì)立即返回連接正確響應(yīng),這樣一個(gè)網(wǎng)絡(luò)連接就成功建立了。
(3)建立網(wǎng)絡(luò)流。客戶端發(fā)送 create Stream 協(xié)議包給 RTMP 服務(wù)器,申請(qǐng)建立網(wǎng)絡(luò)流(Net Stream)。通道與網(wǎng)絡(luò)流(Net Stream)息息相關(guān)。RTMP 協(xié)議提供了 Ping、Invoke、Audio 和 Video 等通道,用于傳輸不同類(lèi)型的數(shù)據(jù)。單個(gè)網(wǎng)絡(luò)連接上使用交錯(cuò)復(fù)用技術(shù)(在實(shí)際抓包分析時(shí),也不一定就是一個(gè)視頻包,然后一個(gè)音頻包,可能是先發(fā)一組視頻包,然后再發(fā)送音頻包,這樣做的原因分析,在前面的文章也有分析過(guò)),可將不同類(lèi)型的數(shù)據(jù)包同時(shí)通過(guò)不同通道傳輸。可見(jiàn),一個(gè)網(wǎng)絡(luò)連接可包括多條通道,即多條通道并存于一個(gè)連接中。RTMP 協(xié)議是根據(jù)數(shù)據(jù)類(lèi)型和用途,從連接中建立網(wǎng)絡(luò)流并作為通道傳輸相應(yīng)數(shù)據(jù)流。
(4)數(shù)據(jù)傳輸。對(duì)于播放play、刪除流delete、發(fā)布publish、暫停pause、停止stop、重新商定 chunk 大小等數(shù)據(jù)流處理,RTMP 協(xié)議也規(guī)定了相應(yīng)的命令。例如拉流播放,當(dāng)客戶端發(fā)送 play 命令后,RTMP 服務(wù)器會(huì)在建立的網(wǎng)絡(luò)流中向客戶端返回音視頻流,進(jìn)而客戶端播放器接收并解碼數(shù)據(jù)流就可以進(jìn)行播放。
(5)Close 過(guò)程。服務(wù)器在發(fā)送完所有音視頻數(shù)據(jù)之后,或客戶端異常退出,需要釋放網(wǎng)絡(luò)流、網(wǎng)絡(luò)連接等資源,從而最終關(guān)閉 RTMP 協(xié)議通信過(guò)程。
RTMP握手和發(fā)送數(shù)據(jù)的過(guò)程為,握手、建立連接、創(chuàng)建流,數(shù)據(jù)傳輸,結(jié)束組成。完整的過(guò)程如下圖:
RTMP RTMP交互過(guò)程
注意:在RTMP握手之前,TCP的三次握手已經(jīng)成功的建立了連接。
4.Web Socket
Web Socket 協(xié)議是 HTML5 中一種全新的持久化協(xié)議,支持服務(wù)器主動(dòng)推送消息給客戶端,即瀏覽器只需發(fā)送一次請(qǐng)求就可源源不斷地獲取服務(wù)器端的數(shù)據(jù)。Websocket提供基于 TCP 的雙向通道,特別適合構(gòu)建實(shí)時(shí) web 應(yīng)用。
HTTP 及其改進(jìn) Polling 和 Long Poll 技術(shù),也能模擬出實(shí)時(shí) Web 應(yīng)用,但存在帶寬消耗大、CPU 資源占用多以及延遲大等缺點(diǎn)。Web Socket 協(xié)議可以成功地解決這些難題,該協(xié)議具有以下特點(diǎn)。
(1)持久化。Web Socket 連接從建立之后,除非客戶端或服務(wù)器主動(dòng)斷開(kāi)連接,否則就會(huì)一直存在。
(2)雙向性。Web Socket 可看作基于 TCP 的socket(瀏覽器暫不支持 socket),提供全雙工通信。當(dāng)使用 Web Socket 協(xié)議時(shí),服務(wù)器可以主動(dòng)推送消息給瀏覽器,實(shí)現(xiàn)真正的實(shí)時(shí)通信。
Web Socket 協(xié)議主要包含兩部分:Web Socket 握手和 Web Socket 數(shù)據(jù)幀。當(dāng)我們使用 Web Socket 協(xié)議傳輸數(shù)據(jù)時(shí),客戶端必須先按照 Web Socket 的握手機(jī)制與服務(wù)器建立連接。握手成功便建立 Web Socket 連接,客戶端與服務(wù)器間就可以按照 Web Socket 數(shù)據(jù)幀格式雙向傳輸數(shù)據(jù)。
Web Socket 協(xié)議存在 6.5、10、13 等多個(gè)草案,導(dǎo)致其具有多個(gè)版本的握手協(xié)議。各個(gè)版本間存在較大差異。差異如下圖:
如果是基于SHA-1 的方式的 Web Socket 握手機(jī)制。草案文檔 RFC6455。為了簡(jiǎn)單化以及兼容 HTTP 程序,Web Socket 協(xié)議采用了 HTTP 的握手形式,并對(duì)其進(jìn)行了修改。握手機(jī)制,包括以下三個(gè)步驟:
(3)客戶端向服務(wù)器發(fā)送特殊的 GET 請(qǐng)求。除了包括正常的 HTTP 頭部,Web Socket握手請(qǐng)求頭部還會(huì)添加 Upgrade、Connection 以及 Sec-Web Socket-Key 等字段。前兩個(gè)字段表示 HTTP 升級(jí)到 Web Socket,Sec-Web Socket-Key 用于安全校驗(yàn)。
(4)服務(wù)器返回 Web Socket 握手應(yīng)答。服務(wù)器返回“101 Switching Protocols”狀態(tài)行與 Upgrade、Connection 以及 Sec-Web Socket-Accept 等響應(yīng)頭部信息。
Sec-Web Socket-Accept 計(jì)算過(guò)程:服務(wù)器取出 Sec-Web Socket-Key 字段,然后與全局唯一標(biāo)識(shí)(GUID)“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”字串進(jìn)行拼接并做 SHA-1 計(jì)算,接著對(duì)得到 SHA-1 結(jié)果進(jìn)行一次 base64 加密。
(5)瀏覽器驗(yàn)證收到的握手應(yīng)答。基于 Sec-Web Socket-Key,客戶端采用同樣的計(jì)算方式,獲得 Sec-Web Socket-Accept。如果客戶端計(jì)算值與服務(wù)器返回對(duì)應(yīng)字段值一致,握手成功。
通過(guò)握手,客戶端與服務(wù)器便建立了 Web Socket 連接。接著,二者就可以基于Web Socket 數(shù)據(jù)幀格式進(jìn)行相互通信。Web Socket 數(shù)據(jù)幀的結(jié)構(gòu),如下圖所示:
Web Socket 數(shù)據(jù)幀
由于負(fù)載的長(zhǎng)度可變,Web Socket 數(shù)據(jù)幀頭部的長(zhǎng)度也是可變的。Web Socket 數(shù)據(jù)幀頭部基本部分,字段解釋如下:
(6)FIN:1bit:標(biāo)記幀是否結(jié)束。
(7)RSV1-3:RSV1,RSV2,RSV3擴(kuò)展位各1bit,一般都為0。
(8)OPCODE:表示負(fù)載類(lèi)型,只定義為0x0-0x A,用4bit表示,不同類(lèi)型如下:
OPCODE 類(lèi)型
(9)MASK:掩碼處理標(biāo)記,1bit表示,如果是1,Payload Data 需要經(jīng)過(guò)掩碼處理。
(10)Extended payload Length :負(fù)載長(zhǎng)度,是可變的,大小是7bits、23bits、71bits。
當(dāng) Web Socket 數(shù)據(jù)幀 Payload 在 0-125 字節(jié)之間,Payload length 占 7bits;當(dāng) Web Socket數(shù)據(jù)幀Payload 在 126-65535 字節(jié)之間,Payload length 占 7+16bits,其中前 7bits 值為 126,后 16bits 表示幀 Payload 長(zhǎng)度;當(dāng) Web Socket 數(shù)據(jù)幀 Payload 超過(guò) 65535 字節(jié),Payloadlength 占 7+64bits,其中前 7bits 值為 127,后 64bits 表示幀 Payload 長(zhǎng)度。長(zhǎng)度表示遵循一個(gè)原則,用最少的字節(jié)表示幀長(zhǎng)度 payload,這種設(shè)計(jì)思想,在有些協(xié)議中也能體現(xiàn)出來(lái)。
注意:Web Socket 數(shù)據(jù)幀還可以分片,詳細(xì)可以參考RFC6455文檔。
4.1 Web Socket API
Web Socket API是 HTML5 為瀏覽器操作 Web Socket 所提供的一組方法。首先,有必要了解瀏覽器對(duì) Web Socket 的支持情況,如下圖所示:
火狐(Firefox):大于等于4.0版本才支持。
谷歌(Chrome):大于等于4.0版本才支持。
IE 瀏覽器(Internet Explorer):大于等于9.0版本才支持。
Opera:大于等于10.0版本才支持。
Safari:大于等于5.0版本才支持。
由此可見(jiàn),主流的瀏覽器都已經(jīng)支持 Web Socket 功能。HTML5 為 Web 開(kāi)發(fā)人員提供非常簡(jiǎn)單的 Web Socket API。以’ws’或’wss’開(kāi)頭形式的成員 URL,表示 Web Socket 服務(wù)器的地址,作為客戶端 new一個(gè) Web Socket 對(duì)象的參數(shù)。Web Socket 幀包括三種狀態(tài) CONNECTION、OPEN 以及CLOSED;還包括 TEXT_FRAME、BINARY_FRAME、PING_FRAME、PONG_FRAME以及 CLOSING_FRAME 等 9 種幀類(lèi)型。
(1)Send()方法用于向 Web Socket 服務(wù)器發(fā)送數(shù)據(jù)。
(2)Close()方法可以關(guān)閉連接。
Web Socket API 還提供三個(gè)重要的事件方法:onopen()、onmessage()以及 onerror()。三個(gè)方法的解釋如下:
(3)onopen():客戶端創(chuàng)建的 Web Socket 對(duì)象與服務(wù)器握手成功后,觸發(fā)該事件。表示客戶端成功建立 Web Socket 連接。
(4)onmessage():服務(wù)器端發(fā)送的數(shù)據(jù)到達(dá)客戶端時(shí),自動(dòng)觸發(fā)該事件方法。該方法是 Web Socket API 最重要方法,開(kāi)發(fā)人員可以實(shí)現(xiàn)對(duì)數(shù)據(jù)的處理。
(5)onerror() :網(wǎng)絡(luò)異常、服務(wù)器中斷等導(dǎo)致響應(yīng)異常,觸發(fā)該事件方法。
5.HTML5 技術(shù)
2007 年 W3C(World Wide Web Consortium,萬(wàn)維網(wǎng)聯(lián)盟)立項(xiàng) HTML5,經(jīng)過(guò)八年的時(shí)間正式成為規(guī)范。HTML5 徹底顛覆了 Flash、IE 霸主的 PC 網(wǎng)絡(luò)格局,還優(yōu)化了移動(dòng)互聯(lián)網(wǎng)的性能。它新增 manifest 離線存儲(chǔ)、Audio 和 Video 流媒體、canvas 和 webbgl游戲以及 Web Socket API 等新特性元素。
(1)Web Workers 是 W3C 在制定 HTML5 草案中提出的,實(shí)現(xiàn)了多線程的支持。WebWorkers 允許開(kāi)發(fā)者編寫(xiě)后臺(tái)長(zhǎng)時(shí)間運(yùn)行(響應(yīng))Java Script,且不會(huì)中斷頁(yè)面的其他容器響應(yīng)。它主要有三個(gè)優(yōu)點(diǎn):長(zhǎng)時(shí)間運(yùn)行、性能理想以及內(nèi)存消耗低。
(2)在某 Java Script 文件代碼中,傳入另一個(gè) Java Script 文件名作為參數(shù),我們可以 new一個(gè) Worker 實(shí)例。HTML5 為 Web Workers 提供非常簡(jiǎn)單的 API,主要包括 post Message()、onmessage()、onclose()以及 onerror()。其中,post Message()方法用于 worker 間發(fā)送消息;onmessage()是 worker 的"onmessage" 事件監(jiān)聽(tīng)器回調(diào)執(zhí)行方法。
(3)Web Workers 后臺(tái)運(yùn)行的特性,特別適合 Web 瀏覽器對(duì)視音頻的處理。本文使用Web Workers 傳遞 Web Socket 數(shù)據(jù)幀,實(shí)現(xiàn)高效地組裝、解析以及編解碼等過(guò)程。
(4)Java Script 提供功能強(qiáng)大的數(shù)組容器,如 Array、Array Buffer,但都不太適合處理視音頻二進(jìn)制數(shù)據(jù)。Typed Array 是 HTML5 引入操作二進(jìn)制數(shù)據(jù)的一個(gè)接口,可以直接操作內(nèi)存。Typed Array 提供了 setter、getter、set 和 subarray 四個(gè)數(shù)據(jù)操作方法。這4個(gè)方法如下解釋:
Typed Array Typed Array 數(shù)據(jù)操作方法
5.1 Typed Array
Typed Array 一般都建立在 Array Buffer 對(duì)象之上。這里簡(jiǎn)述 Typed Array 定義過(guò)程。
(1)首先,通過(guò) Array Buffer,創(chuàng)建指定長(zhǎng)度的連續(xù)內(nèi)存區(qū)域的對(duì)象。接著,基于 Array Buffer對(duì)象,我們創(chuàng)建多種類(lèi)型的“視圖”,即 Typed Array 對(duì)象。
(2)Typed Array 類(lèi)型以類(lèi)型+長(zhǎng)度+Array 命名,常用的有:Int8Array、 Uint8Array、Int16Array、 Uint16Array、Int32Array、Uint32Array、Float32Array 以及 Float64Array。
(3)Typed Array 操作二進(jìn)制數(shù)據(jù)十分高效。還可以使用Typed Array 的 Data View進(jìn)行更復(fù)雜的二進(jìn)制操作。
6. Nginx講解
Nginx 是目前 Web 領(lǐng)域中最出色的 Server 之一,提供一種基于事件驅(qū)動(dòng)、全異步處理以及非阻塞機(jī)制的平臺(tái),善于處理高并發(fā)和實(shí)時(shí)請(qǐng)求應(yīng)用。前面文章列表中給出了Nginx源碼分析,也可以參考前面的文章。
本文從Nginx的跨平臺(tái),容器庫(kù)和獨(dú)創(chuàng)性三個(gè)角度,研究和分析Nginx“獨(dú)創(chuàng)”數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)原理和特色。還會(huì)重述Nginx架構(gòu)設(shè)計(jì),包括啟動(dòng)框架、事件框架/第三方RTMPm=模塊的RTMP框架。
6.1 Nginx數(shù)據(jù)結(jié)構(gòu)
Nginx 實(shí)現(xiàn)了跨平臺(tái)特性,自造了大量且高性能的容器庫(kù),優(yōu)化和改進(jìn)了不少 C 語(yǔ)言數(shù)據(jù)類(lèi)型,獨(dú)創(chuàng)了很多“Nginx 特色”的數(shù)據(jù)結(jié)構(gòu)。
6.1.1 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)跨平臺(tái)
Nginx 對(duì) C 語(yǔ)言數(shù)據(jù)類(lèi)型在每一種操作系統(tǒng)都給出了一份特異化的實(shí)現(xiàn)。下面以有符號(hào)整型(ngx_int_t)為例, 如下圖所示。Nginx 對(duì) int(Windows)、intptr_t(Linux)等“有符號(hào)整型”進(jìn)行 typedef 的封裝,實(shí)現(xiàn)一種跨平臺(tái)類(lèi)型 ngx_int_t。當(dāng) Nginx 在啟動(dòng)的時(shí)候,通過(guò)執(zhí)行 auto/os 下腳本檢測(cè)操作系統(tǒng)環(huán)境,進(jìn)而選擇對(duì)應(yīng)的平臺(tái)上 C 語(yǔ)言類(lèi)型。在 Nginx 模塊開(kāi)發(fā)中,當(dāng)確定為 Linux 平臺(tái),可以使用 intptr_t、u_char 等系統(tǒng)強(qiáng)相關(guān)的 C 語(yǔ)言類(lèi)型。但是仍然強(qiáng)烈建議采用 Nginx 提供數(shù)據(jù)類(lèi)型,因其具有跨平臺(tái)特性。
ngx_int_t 類(lèi)型跨平臺(tái)原理
6.1.2 容器庫(kù)
STL(Standard Template Library,標(biāo)準(zhǔn)模板庫(kù))為 C++開(kāi)發(fā)者提供了 vector、list、set和 map 等容器。作為由 C 實(shí)現(xiàn)的 Nginx,無(wú)法直接使用 STL 中高性能的容器。為了讓Nginx 開(kāi)發(fā)人員享有類(lèi)似的容器,Igor Sysoev 參考了 STL 使用 C 語(yǔ)言重新實(shí)現(xiàn)了一套帶有 Nginx 特色的容器。ngx_array_t、ngx_list_t、ngx_queue_t、ngx_rbtree_t 以及 ngx_hash_t等等。
ngx_list_t 是一種存儲(chǔ)數(shù)組的單鏈表,可以看成普通數(shù)組與 STL 提供 list 的結(jié)合體,內(nèi)存結(jié)構(gòu)如下圖所示:
ngx_list_t 內(nèi)存圖
ngx_list_t 與 list 具有類(lèi)似功能和作用,但是 ngx_list_t 設(shè)計(jì)更加巧妙,因而性能更好。
(1)ngx_list_t 可以存放任意類(lèi)型數(shù)據(jù)類(lèi)型,只需使用成員 size 指定類(lèi)型大小。
(2)ngx_list_t 使用內(nèi)存池 pool 統(tǒng)一管理內(nèi)存,并且鏈表的每個(gè) part 為固定長(zhǎng)度的數(shù)組,數(shù)組所占用的空間為 size*nalloc。
(3)ngx_list_t 局部使用數(shù)組訪問(wèn)元素,大大提高了訪問(wèn)的效率;全局采用單鏈表方式,便于快速添加、刪除等操作。
注意:這種思想是非常值得學(xué)習(xí)和借鑒,但是實(shí)現(xiàn)復(fù)雜度有提高了。
6.1.3 獨(dú)創(chuàng)性
(1)C 語(yǔ)言中,字符串類(lèi)型必須以’>C 語(yǔ)言中,字符串類(lèi)型必須以’\0’字符(空字符)結(jié)尾。Nginx 創(chuàng)造了一種帶長(zhǎng)度的字符串類(lèi)型 ngx_str_t,在路徑src/core/ngx_string.h定義源碼如下:<’字符(空字符)結(jié)尾。Nginx 創(chuàng)造了一種帶長(zhǎng)度的字符串類(lèi)型 ngx_str_t,在路徑src/core/ngx_string.h定義源碼如下:
typedef struct{
size_t len;//字符串的長(zhǎng)符
u_char *data;//字符串的首地址
}ngx_str_t;
這種設(shè)計(jì),可以有效的減少內(nèi)存資源的使用。一個(gè)長(zhǎng)度為 100 的字符串使用 C 字符串需要空間大小為 101bytes。若采用 ngx_str_t,僅僅占用 sizeof(size_t)+sizeof(u_char*)大小空間(假設(shè) 64 位 OS,空間大小為 8+8=16bytes)。這種設(shè)計(jì),同時(shí)便于保持字符串的同步。當(dāng)我們定義字符串時(shí)候,我們只分配一份字符串空間。該字符串的所有使用者都是通過(guò)首地址和長(zhǎng)度來(lái)操作,因此每個(gè)使用者都對(duì)同一份字符串進(jìn)行操作。
(2)Nginx 還獨(dú)創(chuàng)了一種內(nèi)存池(ngx_pool_t)類(lèi)型,其提供一種機(jī)制,幫助統(tǒng)一管理一系列資源(如內(nèi)存、文件等),以免遺漏。通過(guò)使用內(nèi)存池,將多次向系統(tǒng)申請(qǐng)內(nèi)存的操作整合成一次,避免出現(xiàn)內(nèi)存碎片、減少 cpu 資源的消耗。
(3)ngx_buf_t 也是 Nginx 獨(dú)創(chuàng)的一種數(shù)據(jù)結(jié)構(gòu),可以指向內(nèi)存某緩沖區(qū),也可以指向文件某一部分,還可以是純?cè)獢?shù)據(jù)。ngx_buf_t 本質(zhì)上提供僅僅是一些指針成員和標(biāo)志位,并且標(biāo)志位的設(shè)置和使用可以根據(jù)實(shí)際應(yīng)用靈活變動(dòng)。作為一般的使用者,我們只需要掌握常用的部分成員,如 pos、last、end、temporary、last_buf,如下圖所示:
ngx_buf_t
還有ngx_listening_t、ngx_event_t、ngx_connection_t 以及 ngx_http_request_t,可以參考前面的文章,如果還沒(méi)講到的,以后再講。
6.2 Nginx 框架
在 Nginx 中,除了一些核心代碼以外,其余代碼都是以模塊的形式出現(xiàn)。目前,Nginx官方提供 6 種核心模塊,如 ngx_core_module、ngx_http_module 以及 ngx_events_module。在核心模塊中,可自由定義全新的模塊類(lèi)型。官方還提供大量的非核心模塊,可分為四類(lèi):配置模塊、事件模塊、HTTP 模塊和 MAIL 模塊。除此之外,Wiki 論壇還為 Nginx提供大量的第三方模塊,如 nchan。所有模塊之間都是分層次、分類(lèi)別,各類(lèi)模塊的結(jié)構(gòu)如下圖所示:
Nginx 模塊結(jié)構(gòu)
6.2.1 啟動(dòng)框架
啟動(dòng)框架說(shuō)明了 Nginx 啟動(dòng)過(guò)程,是 Nginx 一切應(yīng)用的基礎(chǔ)。啟動(dòng)從 core/nginx.c文件中 main 函數(shù)啟動(dòng)的,啟動(dòng)全部過(guò)程都與 ngx_cycle_t 類(lèi)型全局變量 ngx_cycle 有關(guān)。啟動(dòng)過(guò)程如下所示:
(1)根據(jù)命令行參數(shù)得到配置文件路徑。
(2)如果需要平滑升級(jí),調(diào)用ngx_add_inherited_socket方法 。
(3)調(diào)用所有核心模塊的create_conf方法生成存放配置項(xiàng)的結(jié)構(gòu)體。
(4)通過(guò)nginx.conf解析配置項(xiàng),解析過(guò)程按照樹(shù)深度遞歸。
(5)調(diào)用所有核心模塊的init_conf方法。
(6)添加文件或目錄,初始化shared_memory。
(7)調(diào)用ngx_open_listening_sockets方法,打開(kāi)所有監(jiān)聽(tīng)端口。
(8)調(diào)用所有模塊的init_module方法。
(9)檢測(cè)Nginx是否運(yùn)行。
(10)如果運(yùn)行了,就進(jìn)入master-worker多進(jìn)程模式。先運(yùn)行master進(jìn)程。接著調(diào)用worker進(jìn)程,調(diào)用所有模塊的init_process方法,緊接著啟動(dòng)cache manager進(jìn)程,最后啟動(dòng)cache loader子進(jìn)程。
(11)若還沒(méi)有運(yùn)行就先進(jìn)入單進(jìn)程模式。調(diào)用所有模塊的init_process方法。
第 3-8 步實(shí)現(xiàn) ngx_cycle 的初始化,被封裝于 ngx_init_cycle 函數(shù)。該函數(shù)除了對(duì)各種 ngx_array_t、ngx_list_t 成員初始化外,還包括:創(chuàng)建、解析所有核心模塊配置,打開(kāi)所有監(jiān)聽(tīng)的套接字,調(diào)用所有模塊初始化方法。
啟動(dòng)框架根據(jù)全局變量 ngx_process值,選擇 Nginx 工作循環(huán),圖中為 9 步以后操作。工業(yè)生產(chǎn)中,建議使用 master-worker多進(jìn)程模式。Master 進(jìn)程執(zhí)行 process cycle 啟動(dòng)、監(jiān)控、管理子進(jìn)程,還會(huì)調(diào)用所有模塊 init_process 方法來(lái)初始化對(duì)應(yīng) worker 進(jìn)程。Worker 進(jìn)程執(zhí)行 process cycle,處理網(wǎng)絡(luò)、定時(shí)器等事件,主要調(diào)用事件框架中 ngx_process_events_and_timers()方法工作。
Nginx 啟動(dòng)過(guò)程還有一個(gè)非常重要的工作:解析配置項(xiàng)。Nginx 設(shè)計(jì)了一種最底層的模塊 NGX_CONF_MODULE 類(lèi)型,用于解析所有模塊的配置項(xiàng)。Nginx 對(duì)配置項(xiàng)解析方法 ngx_conf_parse()是以樹(shù)形式,按樹(shù)層次遍歷遞歸進(jìn)行解析,如下圖所示:
Nginx Nginx解析配置項(xiàng)
6.2.2 事件框架
Nginx 的高性能在某種程度上要?dú)w功于其優(yōu)秀的事件框架。事件框架可分為網(wǎng)絡(luò)事件模塊和定時(shí)器事件模塊。本文介紹網(wǎng)絡(luò)事件模塊,可分為 3 層次,如下所示:
(1)第一層:ngx_events_module屬于核心模塊。定義事件類(lèi)型模塊接口、解析”events{}”塊配置項(xiàng)、定義回調(diào) set 方法管理所有事件模塊配置項(xiàng)的結(jié)構(gòu)體(創(chuàng)建、解析與初始化)。核心模塊 ngx_events_module 的 set 方法處理流程如下圖所示:
ngx_events_module ngx_events_module模塊的流程圖
(2)第二層:ngx_event_core_module,第一個(gè)事件模塊。創(chuàng)建連接池(包括讀|寫(xiě)事件)、決定事件驅(qū)動(dòng)機(jī)制、初始化所選用的事件驅(qū)動(dòng)模塊。第二層模塊大部分功能都是 ngx_event_process_init()實(shí)現(xiàn),方法流程如下圖所示:
ngx_event_process_init 方法流程
ngx_event_process_init 方法在啟動(dòng)框架中調(diào)用。nginx 在啟動(dòng)階段就預(yù)設(shè)分配好所有的連接(組成連接池),當(dāng)有客戶端產(chǎn)生連接時(shí)只需直接從連接池中獲取即可使用。配置指令 use 設(shè)置所選擇的事件模塊得序號(hào)(即 ctx_index),ngx_event_process_init 方法僅僅在所有的事件模塊中找到 ctx_index 序號(hào)的事件模塊。ngx_event_process_init 方法將連接的讀事件設(shè)為 ngx_event_accept,并將這些讀事件添加到事件驅(qū)動(dòng)模塊中,進(jìn)而具體的事件驅(qū)動(dòng)模塊會(huì)檢測(cè)監(jiān)聽(tīng)服務(wù),處理用戶新連接。
(3)第三層:ngx_select_module,事件驅(qū)動(dòng)實(shí)際處理模塊,共 9 種,常用 epoll 模塊。
其它:ngx_epoll_module、ngx_kqueue_module等等。基于 OS 的系統(tǒng)調(diào)用,每個(gè)模塊都實(shí)現(xiàn)事件類(lèi)型模塊接口所定義的 10 個(gè)抽象方法,如 init、add、del以及 process_events 等。
(4)事件框架的 ngx_process_events_and_timers 方法,在啟動(dòng)框架中 worker 的工作循環(huán)中調(diào)用,循環(huán)處理所有的事件,是事件驅(qū)動(dòng)機(jī)制的核心。主要包括 3 項(xiàng)工作,如下:
第一,調(diào)用所選擇的事件驅(qū)動(dòng)模塊的process_events方法,處理網(wǎng)絡(luò)事件。
第二,處理兩個(gè)post事件隊(duì)列中的事件。
第三,處理定時(shí)器事件。
對(duì)于事件框架,Nginx 開(kāi)發(fā)者需要熟悉事件模塊常見(jiàn)的外部使用方法,如下所示:
事件模塊中常見(jiàn)的外部接口事件模塊中常見(jiàn)的外部接口
7.RTMP 框架
RTMP 框架是 Nginx 的第三方模塊“nginx-rtmp-module”,包含幾十個(gè)源文件,使Nginx 成為一種支持 RTMP 協(xié)議的 Flash 服務(wù)器。目前,RTMP 框架具有支持 flv/mp4 視頻流、支持 push and pull 分發(fā)模式、支持 H264/ACC 編碼、支持 HLS、支持 FFmpeg 轉(zhuǎn)碼及支持 exec 等功能。RTMP 框架可細(xì)分為 ngx_rtmp_module、ngx_rtmp_core_module等數(shù)十個(gè)模塊,這些模塊構(gòu)成了 RTMP 四層次體系,如下圖所示:
RTMP RTMP框架體系
下面給出 RTMP 框架基于事件的執(zhí)行流程,如下圖所示:
RTMP RTMP執(zhí)行流程
8.總結(jié)
本文介紹了視頻會(huì)議的PC客戶端和web端的相關(guān)協(xié)議介紹,包括TCP、RTP/RTCP、RTMP及WebSocket協(xié)議。接著介紹了HTML5標(biāo)準(zhǔn)Web Worker和Type Array技術(shù)。最好介紹了Nginx,RTMP的相關(guān)流程分析。接下來(lái)的文章會(huì)講講多協(xié)議之間如何設(shè)計(jì)。歡迎關(guān)注,收藏,轉(zhuǎn)發(fā),分享。
后期關(guān)于項(xiàng)目知識(shí),也會(huì)更新在微信公眾號(hào)“記錄世界 from antonio”,歡迎關(guān)注
HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件源代碼,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件代碼,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件源碼,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件組件,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件控件,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件方案,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件技術(shù),用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件軟件,用HTML5實(shí)現(xiàn)分片上傳GB級(jí)大文件服務(wù),用javascript實(shí)現(xiàn)分片上傳GB級(jí)大文件源代碼,用js實(shí)現(xiàn)分片上傳GB級(jí)大文件源代碼,用vue2實(shí)現(xiàn)分片上傳GB級(jí)大文件源代碼,用vue3實(shí)現(xiàn)分片上傳GB級(jí)大文件源代碼,
用戶上傳的文件比較大,有20G左右,直接用HTML傳的話容易失敗,服務(wù)器也容易出錯(cuò),需要分片,分塊,分割上傳。也就是將一個(gè)大的文件分成若干個(gè)小文件塊來(lái)上傳,另外就是需要實(shí)現(xiàn)秒傳功能和防重復(fù)功能,秒傳就是用戶如果上傳過(guò)這個(gè)文件,那么直接在數(shù)據(jù)庫(kù)中查找記錄就行了,不用再上傳一次,節(jié)省時(shí)間,實(shí)現(xiàn)的思路是對(duì)文件做MD5計(jì)算,將MD5值保存到數(shù)據(jù)庫(kù),算法可以用MD5,或者CRC,或者SHA1,這個(gè)隨便哪個(gè)算法都行。
分片還需要支持?jǐn)帱c(diǎn)續(xù)傳,現(xiàn)在HTML5雖然提供了信息記錄功能,但是只支持到了會(huì)話級(jí),也就是用戶不能關(guān)閉瀏覽器,也不能清空緩存。但是有的政府單位上傳大文件,傳了一半下班了,明天繼續(xù)傳,電腦一關(guān)結(jié)果進(jìn)度信息就丟失了,這個(gè)是他們的一個(gè)痛點(diǎn)。
切片的話還有一點(diǎn)就是在服務(wù)器上合并,一個(gè)文件的所有分片數(shù)據(jù)上傳完后需要在服務(wù)器端進(jìn)行合并操作。
功能的話支持20G文件上傳和續(xù)傳,支持秒傳,支持文件夾上傳,支持在服務(wù)端保存文件夾層級(jí)結(jié)構(gòu),支持將文件夾層級(jí)結(jié)構(gòu)信息保存到數(shù)據(jù)庫(kù)中,支持下載時(shí)能夠?qū)⑽募A層級(jí)結(jié)構(gòu)下載下來(lái),支持下載文件夾,下載文件夾支持?jǐn)帱c(diǎn)續(xù)傳,支持VUE2,VUE3,React,支持IE,Chrome和信創(chuàng)國(guó)產(chǎn)化環(huán)境,比如銀河麒麟,統(tǒng)信UOS,龍芯,支持加密傳輸,包括加密上傳,加密下載,加密算法支持國(guó)密SM4,支持云對(duì)象存儲(chǔ),比如華為云,阿里云,騰訊云,七牛云,AWS,MinIO,FastDFS,需要提供手機(jī),QQ,微信,郵箱等聯(lián)系方式,提供7*24小時(shí)技術(shù)支持,提供長(zhǎng)期技術(shù)支持和維護(hù)服務(wù),提供遠(yuǎn)程1對(duì)1技術(shù)指導(dǎo),提供二次開(kāi)發(fā)指導(dǎo),提供文檔教程,提供視頻教程。
1.下載示例
https://gitee.com/xproer/up6-vue-cli
將up6組件復(fù)制到項(xiàng)目中
示例中已經(jīng)包含此目錄
1.引入up6組件
2.配置接口地址
接口地址分別對(duì)應(yīng):文件初始化,文件數(shù)據(jù)上傳,文件進(jìn)度,文件上傳完畢,文件刪除,文件夾初始化,文件夾刪除,文件列表
參考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de
3.處理事件
啟動(dòng)測(cè)試
啟動(dòng)成功
效果
數(shù)據(jù)庫(kù)
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。