一、RTMP 协议概述
今天我们要一起了解的这个协议叫 RTMP 协议,它并不复杂,对于拉流相关的协议,我们可以先思考一下拉流一般要交互什么,我理解有以下几项,
- 连接信息:包括服务器的地址、端口号等,以建立与流媒体源的连接。
- 认证信息:如果需要进行用户认证或授权访问,可能需要交互用户名、密码或令牌等认证凭据。
- 流标识:明确要拉取的具体流媒体内容的标识,例如频道号、视频 ID 等,这个也可以在协议中直接约定。
- 控制指令:例如播放、暂停、快进、快退等控制操作的指令。
- 媒体描述:指定所需的视频或音频质量,如分辨率、帧率、码率等。
- 缓冲设置:包括缓冲区大小、缓冲策略等,以优化流媒体播放的流畅性。
- 错误报告和状态反馈:向服务器报告拉流过程中出现的错误,同时接收服务器关于流的状态信息,如是否可用、是否中断等。
知道了协议设计的目的,对协议的理解就更加方便了。
1.1 RTMP 协议
RTMP 是 Real Time Messaging Protocol( 实时消息传输协议) 的首字母缩写。该协议基于 TCP,是一个协议族,包括 RTMP 基本协议及 RTMPT/RTMPS/RTMPE 等多种变种。
RTMP(Real Time Messaging Protocol)实时消息传送协议是 Adobe Systems 公司为 Flash 播放器和服务器之间音频、视频和数据传输开发的开放协议。
作为应用层协议,RTMP是建立在TCP上的,在TCP建立完成后,RTMP通过握手,来见RTMP的connection。
在这个connection上,会传输一些控制信息,比如SetChunkSize,SetAckWinowSize,其中CreateStream命令会创建一个Stream连接,
RTMP 协议传输时会对数据格式化,而实际传输的时候为了更好地实现多路复用、分包和信息的公平性,发送端会把 Message 划分为带有 Message ID 的 Chunk,每个 Chunk 可能是一个单独的 Message,也可能是 Message 的一部分,在接收端会根据 Chunk 中包含的 data 的长度,message id 和 message 的长度把 chunk 还原成完整的 Message,从而实现信息的收发。 即RTMP基本的逻辑单元是Message,基本的传输单元是Chunk。
1.2、变种
它有多种变种:
- RTMP 工作在 TCP 之上,默认使用端口 1935;
- RTMPE 在 RTMP 的基础上增加了加密功能;encrypt
- RTMPT 封装在 HTTP 请求之上,可穿透防火墙;http–rtmp
- RTMPS 类似 RTMPT,增加了 TLS/SSL 的安全功能;
1.3 RTMP和RTSP的区别
RTMP 和 RTSP 都是流媒体传输协议,它们在实时音视频传输方面有着广泛的应用。以下是它们之间的主要区别:
-
实时传输协议:RTMP 是一种基于 TCP 的实时传输协议,而 RTSP 是一种基于 UDP 的实时传输协议。
-
传输方式:RTMP 是一种单向传输协议,信息只能从服务器端传输到客户端。而 RTSP 支持双向传输,允许服务器端和客户端之间进行实时通信。
-
控制协议:RTSP 是一种控制协议,它可以用于控制媒体流的播放、暂停、停止等操作。而 RTMP 不是一种控制协议,它只负责媒体流的传输。
-
安全性:RTMP 提供了较低的安全性,因为它使用 TCP 协议进行传输,容易受到中间人攻击。而 RTSP 提供了较高的安全性,因为它使用 UDP 协议进行传输,并支持加密和认证。
-
应用场景:RTMP 主要用于直播和视频点播应用,而 RTSP 主要用于实时视频监控和安防监控等应用。
二、RTMP协议详解
RTMP传输的数据被称为消息(Message),这些消息包括音视频数据和信令,但某些消息可能很大,所以这些Message还会被分块传输,这样的块被称为Chunk。Chunk中带有message id,用于指示它属于哪个消息,接收端根据这个id来组成完整的消息。
即RTMP基本的逻辑单元是Message,基本的传输单元是Chunk。
2.1 Chunk的基本组成
- 基本头:基本头包含了分块的基本信息。chunk stream ID(流通道Id)和chunk type(chunk的类型)
- 消息头:消息头包含了分块的扩展时间戳(如果有)和分块的长度信息。
- 扩展时间戳:如果消息头中的时间戳字段取值为0xFFFFFF,则表示时间戳需要通过扩展时间戳字段来传输。*
- 负载(Payload):负载部分包含了分块的实际数据,可能是音视频数据或者是控制信令。
2.1.1 Basic Header
包含了chunk stream ID(流通道Id)和chunk type(chunk的类型),chunk stream id⼀般被简写为CSID,⽤来唯⼀标识⼀个特定的流通道,chunk type决定了后⾯Message Header的格式。BasicHeader的⻓度可能是1,2,或3个字节,其中chunk type的⻓度是固定的(占2位),Basic Header是变⻓的,其⻓度取决于CSID的⼤⼩,在⾜够存储这两个字段的前提下最好⽤尽量少的字节从⽽减少由于引⼊Header增加的数据量。
长度如何计算再此不赘述。
2.1.2 Message Header
包含了要发送的实际信息(可能是完整的,也可能是⼀部分)的描述信息。Message Header的格式和⻓度取决于Basic Header的chunk type,共有4种不同的格式,由上⾯所提到的Basic Header中的fmt字段控制。其中第⼀种格式可以表示其他三种表示的所有数据,但由于其他三种格式是基于对之前chunk的差量化的表示,因此可以更简洁地表示相同的数据,实际使⽤的时候还是应该采⽤尽量少的字节表示相同意义的数据。以下按照字节数从多到少的顺序分别介绍这4种格式的Message Header。
- type 0 :11bit
type=0时Message Header占⽤11个字节,其他三种能表示的数据它都能表示,但一般在chunk stream的开始的第⼀个chunk会采用这种类型。
比如onMetaData Message
- type = 1:7bit
- 其他
其它类似,在此也不赘述了。
2.1.3 Extended Timestamp(扩展时间戳)
当chunk中的时间戳或者时间戳差值大于3字节能表示的最大数值(0xFFFFFF = 16777215)时,用这个字段来表示真正的时间戳。
2.1.4 Chunk Data
实际数据
三、RTMP的建连流程
1、建立一个连接,2、建立一个网络流
3.1 建立连接
包括握手和连接相关的参数设置。
3.1.1 握手
要建立一个有效的RTMP连接,首先要握手。客户端向服务器发送C0 C1 C2三个chunk,服务器向客户端发送S0、S1、S2三个chunk,才能开始数据传输。
RTMP协议没有规定这6个MESSAGE的顺序,但是需要保证几点。
1、客户端要收到S1才能发送C2
2、客户端要收到S2后才能发送其他信息
3、服务端要收到C0才能发送S1
4、服务端要收到C2后才能发送其他信息。
但实际中为了尽量减少通信的次数,一般发送顺序是这样的,
其中C0和S0主要是为了交互双方的RTMP协议版本
C1和S1是为了交互双方的时间戳和随机数据,时间戳用于计算双方协议交互的延迟(基本不用),随机数据用于在密钥协商过程中生成密钥。
C2、S2和C1、S1格式是一样的,主要是为了确认回复。
3.1.2 建立网络连接
-
S1. 发送connect到服务器,请求和服务应用实例建立连接
-
S2. 服务端设置客户端的应答窗口大小、发送带宽大小、接收块大小
-
S3 服务端响应创建网络连接的结果
-
S4 客户端设置服务器的接收块大小
3.1.3 建立网络流
-
S1 客户端发送命令消息中的“创建流” (createStream) 命令到服务器端。
-
S2. 服务器端接收到“创建流” 命令后, 发送命令消息中的“结果” (_result), 通知客户端流的状态
-
S3. 客户端向服务器获取指定流的长度
3.1.4 播放
- S1 客户端发送播放请求play
- S2 服务端发送stream begin,告知客户端流id
- S3 服务端开始发送数据
四、RTMP和HLS以及HTTP-FLV的比较
五、总结
本文主要介绍了RTMP协议的相关内容,包括协议概述、协议详解、建连流程以及与其他协议的比较,RTMP是基于TCP的实时消息传输协议,是一个协议族,包括多种变种,变种包括RTMPT、RTMPS、RTMPE等,它们在功能上有所不同。。作为应用层协议,建立在TCP之上,通过握手建立connection,传输控制信息,如SetChunkSize、SetAckWinowSize等,CreateStream命令创建Stream连接。RTMP协议传输时对数据格式化,将Message划分为Chunk,接收端再还原。建连包括建立连接和建立网络流,建立连接包含握手和连接相关的参数设置。握手时客户端和服务器交互C0、C1、C2、S0、S1、S2六个chunk,并遵循一定的顺序和规则。立网络连接和网络流时,客户端和服务器会进行相应的消息交互和参数设置。播放时客户端发送请求,服务器响应并开始发送数据。