rtmplib rtmp協議過程分析
寫的很好,收藏如下,向作者致敬!
沒事碰到了librtmp庫,這個庫是ffmpeg的依賴庫,用來接收,釋出RTMP協議格式的資料。
程式碼在這裡:git clone git://git.ffmpeg.org/rtmpdump
先看一段通過librtmp.so庫下載RTMP源釋出的資料的例子,從rtmpdump中抽取出來。使用的大體流程如下:
- RTMP_Init主要就初始化了一下RTMP*rtmp變數的成員。
- RTMP_SetupURL 函式將rtmp源地址的埠,app,等url引數進行解析,設定到rtmp變數中。比如這樣的地址: rtmp://host[:port]/path swfUrl=url tcUrl=url 。
- RTMP_SetBufferMS 函式設定一下緩衝大小;
- RTMP_Connect函式完成了連線的建立,一級RTMP協議層的應用握手,待會介紹。
- RTMP_ConnectStream總的來說,完成了一個流的建立,以及開啟,觸發服務端傳送資料過來,返回後,服務端應該就開始傳送資料了。
- Download 其實是RTMP_Read函式的封裝,後者讀取服務端的資料返回。
- RTMP_Init(&rtmp);//初始化RTMP引數
- //指定了-i 引數,直接設定URL
-
if (RTMP_SetupURL(&rtmp, fullUrl.av_val) == FALSE) {
- RTMP_Log(RTMP_LOGERROR, "Couldn't parse URL: %s", fullUrl.av_val);
- return RD_FAILED;
- }
- rtmp.Link.timeout = timeout ;
- /* Try to keep the stream moving if it pauses on us */
- if (!bLiveStream )
- rtmp.Link.lFlags |= RTMP_LF_BUFX;
- while (!RTMP_ctrlC)
- {
-
RTMP_Log(RTMP_LOGDEBUG, "Setting buffer time to: %dms", DEF_BUFTIME);
- RTMP_SetBufferMS(&rtmp, DEF_BUFTIME);//告訴伺服器幫我快取多久
- RTMP_LogPrintf("Connecting ...\n");
- if (!RTMP_Connect(&rtmp, NULL)) {//建立連線,傳送"connect"
- nStatus = RD_NO_CONNECT;
- break;
- }
- RTMP_Log(RTMP_LOGINFO, "Connected...");
- //處理服務端返回的各種控制訊息包,比如收到connect的result後就進行createStream,以及傳送play(test)訊息
- if (!RTMP_ConnectStream(&rtmp, 0)) {//一旦返回,表示服務端開始傳送資料了.可以play了
- nStatus = RD_FAILED;
- break;
- }
- nStatus = Download(&rtmp, file, bStdoutMode, bLiveStream );
- if (nStatus != RD_INCOMPLETE || !RTMP_IsTimedout(&rtmp) || bLiveStream)
- break;
- }
一、建立協議連線
下面來詳細介紹下RTMP_Connect函式的工作。
先看程式碼,下面RTMP_Connect的工作是連線對端,進行握手,並且傳送”connect” 控制訊息,附帶一些app,tcurl等引數。其實時呼叫了2個函式完成工作的:RTMP_Connect0, RTMP_Connect1 。
- int RTMP_Connect(RTMP *r, RTMPPacket *cp)
- {//連線對端,進行握手,並且傳送"connect" 控制訊息,附帶一些app,tcurl等引數
- struct sockaddr_in service;
- if (!r->Link.hostname.av_len)
- return FALSE;
- memset(&service, 0, sizeof(struct sockaddr_in));
- service.sin_family = AF_INET;
- if (r->Link.socksport)
- {
- /* Connect via SOCKS */
- if (!add_addr_info(&service, &r->Link.sockshost, r->Link.socksport))
- return FALSE;
- }
- else
- {
- /* Connect directly */
- if (!add_addr_info(&service, &r->Link.hostname, r->Link.port))
- return FALSE;
- }
- if (!RTMP_Connect0(r, (struct sockaddr *)&service))//建立一個socket連線
- return FALSE;
- r->m_bSendCounter = TRUE;
- return RTMP_Connect1(r, cp);//進行C0-2/S0-2協議握手,傳送connect命令
- }
其中RTMP_Connect0 函式比較簡單,標準的socket, conect 流程,另外設定了一下TCP_NODELAY選項,方便小包傳送等。以及SO_RCVTIMEO讀超時,這部分屬於基本的TCP層面的連線;
RTMP_Connect1 函式則完成類似HTTP層面的RTMP協議的連線建立過程。首先是HandShake 握手。RTMP的握手是通過客戶端跟服務端互相傳送資料包來完成的,每人3個數據包,名之為C0,C1,C2 以及S0,S1, S2。其傳送資料有嚴格的限制的。因為互相依賴。這個在官方文件中有詳細的介紹,不多說。
對於librtmp來說,可能的一種流程是:
CLIENT SERVER
C0,C1 —>
<— S0, S1,S2
C2 –>
具體看一下程式碼,比較長。
- static int HandShake(RTMP *r, int FP9HandShake)
- {//C0,C1 -- S0, S1, S2 -- C2 訊息握手協議
- int i;
- uint32_t uptime, suptime;
- int bMatch;
- char type;
- char clientbuf[RTMP_SIG_SIZE + 1], *clientsig = clientbuf + 1;
- char serversig[RTMP_SIG_SIZE];
- clientbuf[0] = 0x03;//C0, 一個位元組。03代表協議版本號為3 /* not encrypted */
- uptime = htonl(RTMP_GetTime());//這是一個時間戳,放在C1訊息頭部
- memcpy(clientsig, &uptime, 4);
- memset(&clientsig[4], 0, 4);//後面放4個位元組的空資料然後就是隨機資料
- //後面是隨機資料,總共1536位元組的C0訊息
- #ifdef _DEBUG
- for (i = 8; i <RTMP_SIG_SIZE; i++)
- clientsig[i] = 0xff;
- #else
- for (i = 8; i <RTMP_SIG_SIZE; i++)
- clientsig[i] = (char)(rand() % 256);//傳送C0, C1訊息
- #endif
- if (!WriteN(r, clientbuf, RTMP_SIG_SIZE + 1))
- return FALSE;
- //下面讀一個位元組也就是S0訊息,看協議是否一樣
- if (ReadN(r, &type, 1) != 1) /* 0x03 or 0x06 */
- return FALSE;
- RTMP_Log(RTMP_LOGDEBUG, "%s: Type Answer : %02X", __FUNCTION__, type);
- if (type != clientbuf[0])//C/S版本不一致
- RTMP_Log(RTMP_LOGWARNING, "%s: Type mismatch: client sent %d, server answered %d", __FUNCTION__, clientbuf[0], type);
- //讀取S1訊息,裡面有伺服器執行時間
- if (ReadN(r, serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
- return FALSE;
- /* decode server response */
- memcpy(&suptime, serversig, 4);
- suptime = ntohl(suptime);
- RTMP_Log(RTMP_LOGDEBUG, "%s: Server Uptime : %d", __FUNCTION__, suptime);
- RTMP_Log(RTMP_LOGDEBUG, "%s: FMS Version : %d.%d.%d.%d", __FUNCTION__, serversig[4], serversig[5], serversig[6], serversig[7]);
- /* 2nd part of handshake */
- if (!WriteN(r, serversig, RTMP_SIG_SIZE))//傳送C2訊息,內容就等於S1訊息的內容。
- return FALSE;
- //讀取S2訊息
- if (ReadN(r, serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
- return FALSE;
- bMatch = (memcmp(serversig, clientsig, RTMP_SIG_SIZE) == 0);
- if (!bMatch)//服務端返回的S2訊息必須跟C1訊息一致才行
- {
- RTMP_Log(RTMP_LOGWARNING, "%s, client signature does not match!", __FUNCTION__);
- }
- return TRUE;
- }
握手的目的其實是互相溝通一下支援的協議版本號,伺服器時間戳等。確保連線的對端真的是RTMP支援的。
傳送請求給服務端。
然後就是SendConnectPacket的工作了。總結一句其功能是成一個“connect訊息以及其app,tcurl等引數,然後呼叫RTMP_SendPacket函式將其資料傳送出去。
到這裡連線建立完成了。
二、準備資料通道
RTMP_ConnectStream完成了通道的建立。其處理服務端返回的各種控制訊息包,比如收到connect的result後就進行createStream,以及傳送play(test)訊息。一旦返回,表示服務端開始傳送資料了.可以play了。
函式本身比較簡單,就是一個while迴圈,不斷的呼叫RTMP_ReadPacket讀取服務端傳送過來的資料包進行相應的處理。直到m_bPlaying變老變為TRUE為止,也就是可以播放的時候為止。資料包的處理函式為RTMP_ClientPacket。
- int RTMP_ConnectStream(RTMP *r, int seekTime)
- {//迴圈讀取服務端傳送過來的各種訊息,比如window ack**, set peer bandwidth, set chunk size, _result等
- //直到接收到了play
- RTMPPacket packet = { 0 };
- /* seekTime was already set by SetupStream / SetupURL.
- * This is only needed by ReconnectStream.
- */
- if (seekTime > 0)
- r->Link.seekTime = seekTime;
-
相關推薦
rtmplib rtmp協議過程分析
寫的很好,收藏如下,向作者致敬! 沒事碰到了librtmp庫,這個庫是ffmpeg的依賴庫,用來接收,釋出RTMP協議格式的資料。 程式碼在這裡:git clone git://git.ffmpeg.org/rtmpdump 先看一段通過librtm
RTMP協議分析及推流過程
簡介: 1.RTMP(實時訊息傳輸協議)是Adobe 公司開發的一個基於TCP的應用層協議。 2.RTMP協議中基本的資料單元稱為訊息(Message)。 3.當RTMP協議在網際網路中傳輸資料的時候,訊息會被拆分成更小的單元,稱為訊息塊(Chunk)。 RTMP 握手(
rtmp 協議分析及互動過程
本文描述了從開啟一個RTMP流媒體到視音訊資料開始播放的全過程。 注意:RTMP中的邏輯結構 RTMP協議規定,播放一個流媒體有兩個前提步驟:第一步,建立一個網路連線(NetConnection);第二步,建立一個網路流(NetStream)。其中,網路連線代表伺服器端應用程式和客戶端之間基礎的連通
調試libRTMP代碼來分析RTMP協議
bind 部分 字節 attribute err nco last esc command RTMP是Real Time Messaging Protocol(實時消息傳輸協議)的首字母縮寫。該協議基於TCP,是一個協議族,常用在視頻直播領域。RTMP協議的默認端口
TCP協議三次握手過程分析
fmt 圖1 同步 建立連接 協議 from pan mir 重置 TCP(Transmission Control Protocol) 傳輸控制協議。 TCP是主機對主機層的傳輸控制協議,提供可靠的連接服務,采用三次握手確認建立一個連接: 位碼即tcp標誌位,有6種標
從wireshark抓包分析rtmp協議,並提取出H264視頻流
tmp mage idt 進制 tro shark src 技術 wid 利用wireshark抓取rtmp流數據, 分析到rtmp流後,寫入過濾條件,如 tcp.stream eq 6導出tcp流保存16進制的數據為純文本格式一定要選擇 Hex轉儲,然後點擊 “Sava
Tcp協議中的3次握手與4次揮手過程分析
轉載https://blog.csdn.net/u012824097/article/details/52490091 客戶端與服務端的通訊中步驟 1建立Tcp連線 3次握手 2再進行資料傳輸 3資料傳輸完成後,斷開連線。
RTMP協議分析
一、RTMP包頭 RTMP協議 封包 參考Red5 RTMP協議封包 由一個包頭和一個包體組成,包頭可以是4種長度的任意一種:12, 8, 4, 1 byte(s).完整的RTMP包頭應該是12bytes,包含了時間戳,Head_Type,AMFSize,AMFT
TCP協議四次揮手過程分析?為什麼握手三次揮手四次?
1. 為什麼四次揮手? 為什麼連線的時候是三次握手,關閉的時候卻是四次握手? 答:因為當Server端收到Client端的SYN連線請求報文後,可以直接傳送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連線時,當Server端
wireshark+rtmp協議分析
使用wireshark抓包工具 如何使用wireshark中常見的過濾選項包括協議型別、埠號、stream eq、ip地址 通過wireshark,要學會如何重網路包中獲取視訊幀的資料,這裡主要針對rtmp協議。 抓取網路包 開啟wire
RTMP協議播放流程的實現及抓包分析
實時流協議(Real-TimeMessaging Protocol,RTMP)是用於網際網路上傳輸視音訊資料的網路協議。本API提供了支援RTMP, RTMPT,RTMPE, RTMP RTMPS以及以上幾種協議的變種(RTMPTE, RTMPTS)協議所需的大
RTMP協議分析及H.264打包原理
RTMP是Real Time Messaging Protocol(實時訊息傳輸協議)的首字母縮寫。該協議基於TCP,是一個協議族,包括RTMP基本協議及RTMPT/RTMPS/RTMPE等多種變種。RTMP是一種設計用來進行實時資料通訊的網路協議,主要用來在Flash/A
視頻rtmp協議簡介
png class 論文 smi false spa codec -i baidu 這篇論文裏講得非常詳細。下面說說我的理解。 server端:將視頻流按順序切割為視頻+音頻合成文件ts,每個ts是視頻流的一塊,並把ts信息存儲在m3u8文件中 client端:讀取m3u
HTTP協議詳細分析
就會 cat purpose 分隔 utf-8 tcp/ip 例如 握手 5.0 1、HTTP概述 1.1、什麽是HTTP? 它是Hyper Text Transfer Protocol的縮寫。超文本傳輸協議。 它是客戶瀏覽器和web服務器之間的
【轉】Android 4.0 Launcher2源碼分析——啟動過程分析
handler flag 這一 第一次啟動 asynctask pla size ontouch wait Android的應用程序的入口定義在AndroidManifest.xml文件中可以找出:[html] <manifest xmlns:android="htt
STM32的flash數據頁轉存過程分析!
pty val 根據 mst else 系統 add ted ble stm32模擬eeprom要實現flash數據頁轉存,實現函數為 1 /** 2 * @brief Transfers last updated variables data from the fu
Linux系統調用過程分析
policy 用戶空間 抽象接口 保護 name ack for 內嵌 驅動程序 參考: 《Linux內核設計與實現》 0 摘要 linux的系統調用過程: 層次例如以下: 用戶程序------>C庫(即API):INT 0x80 ----->system_
流媒體系統的RTMP協議
RTMP協議 流媒體系統 AMF 什麽是RTMP協議 RTMP(Real-Time Messaging Protocol實時消息傳送協議)的縮寫,它是Adobe Systems公司為Flash播放器和服務器之間音頻、視頻和數據傳輸開發的協議。這是一個標準的,未加密
推薦下:開源ckplayer 網頁播放器, 跨平臺(html5, mobile),flv, f4v, mp4, rtmp協議. webm, ogg, m3u8 !
網頁播放器 get ... 默認 control firefox ckplayer 原本 auto 視頻播放, 原本是想h5 自帶視頻播放,使用很簡單,結果現實很骨感。 <video controls="controls" preload="auto" height
X86架構下Linux啟動過程分析
重要 ack csdn 檢查 point article span 註意 eap 1、X86架構下的從開機到Start_kernel啟動的整體過程 這個過程簡要概述為: 開機——>BIOS——>GRUB/LILO——>Linux Kernel