tcpdump抓包:
tcpdump host IP and tcp port 1935 -w a.pcap
whireshark分析:
用wireshark打開a.pcap
3握手(Handshake)
一個RTMP連接以握手開始,我們先看下圖:
首先我們要明確的是客戶端IP是192.168.1.102(我的電腦),123.183.164.23是RTMP服務器。
劇本應該是這樣子的:
-
RTMP協議是TCP協議的上層協議,所以必須要先建立TCP連接,所以就看到了1-4這幾個TCP三次握手的包。
-
客戶端向服務器發送C0塊(chunks),表示要和服務器握手,C0中包含版本號。
-
服務器收到C0後,檢查C0中的版本是否支持,如果支持發送S0作爲響應,否則應該終止連接。
-
客戶端和服務器都分別等待C1和S1,等待版本確認。
-
客戶端收到S1後發送C2,服務器收到C1後發送S2(確認發送,測試握手完成。)
然而,協議的實際執行卻不是按照劇本來的(如果按劇本來,延遲就要大大增大了),實際執行是這樣的:
-
RTMP協議是TCP協議的上層協議,所以必須要先建立TCP連接,所以就看到了1-4這幾個TCP三次握手的包。
-
客戶端發送的是C0+C1塊,直接告訴服務器我發的版本我自己確認了。
-
服務器更狠,一個大嘴巴子就抽回來了(發送S0+S1+S2)。
-
客戶端收到後,發送C2,握手完成!
附上RTMP協議中的流程圖:
有同學站起來提問了,No.13的包是C2,那麼後面的connect是what?這位同學請坐下,往下看。
4建立一個網絡連接(NetConnection)
提示:
網絡連接代表服務器端應用程序和客戶端之間基礎的連通關係。
我們接着看抓到的包:
RTMP握手完成後,要建立網絡連接。大家都知道一個普通的標準的rtmp流是什麼樣子的?rtmp://IP:PORT/APP/Stream 是不是這樣?
實際劇本是這樣子滴:
1.客戶端在發送C2的時候,順帶還發了一個請求連接的命令,要求與服務器應用(live7)建立網絡連接,這就是RTMP URL中的的Application。soga,是不是恍然大悟?
2.服務器在收到客戶端發送的連接請求後發送如下信息:
主要是告訴客戶端確認窗口大小,設置節點帶寬,然後服務器把“連接”連接到指定的應用並返回結果,“網絡連接成功”。並且返回流開始的的消息(Stream Begin 0)。
3.客戶端在收到服務器發來的消息後,返回確認窗口大小(No.18),此時網絡連接創建完成。
協議流程圖:
5建立一個網絡流(NetStream
)
提示:
網絡流代表了發送多媒體數據的通道。
服務器和客戶端之間只能建立一個網絡連接,且多個網絡流可以複用這一個網絡連接。
接着看抓包:
現在地洞挖好了,就差鋪鐵軌了!
-
客戶端向服務器發送設置Buffer Length爲0,3000ms,並請求創建流(createStream)。
-
客戶端向服務器發送一個控制消息(去了,我也不知道幹啥用的!)
-
服務器收到請求後向客戶端發送_result(),對創建流的消息進行響應。此時NetStream創建完成。
協議流程圖:
6播放
提示:
主要功能:傳輸音視頻數據
看抓包:
萬事具備,只欠東風了。
1.客戶端向服務器發送播放命令,請求播放stream,並設置Buffer Length 1,3000ms。
2.服務器收到請求後,向客戶端發送設置塊大小的協議消息,並且還附加了一堆其他的消息一起發送:
包括 Stream Begin(告知客戶端流ID爲0)、NetStream.Play.Reset和NetStream.Play.Start(告知客戶端播放成功,其中reset會調整流ID爲1)等。
3.服務器向客戶端發送推流通知,並附帶元數據信息(分辨率、幀率、音頻採樣率、音頻碼率等等)和視頻、音頻數據。此時客戶端就可以開始正常播放rtmp流了。
協議流程圖:
本文總結了RTMP協議播放環節的全流程,後續文章將爲大家帶來更多RTMP實際輸出中遇到的坑以及優化方案。