rtmp协议详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rtmp协议详解相关的知识,希望对你有一定的参考价值。
参考技术A rtmp连接从握手开始。它包含三个固定大小的块。客户端发送的三个块命名为c0,c1,c2;服务端发送的三个块命名为S0,S1,S2。握手序列:
764 bytes digest 结构:
version(1byte):版本。在C0包内,这个字段代表客户端请求的RTMP版本号。在S0包内,这个字段代表服务端选择的RTMP版本号。当前使用的版本是3。在版本0-2用在早期的产品中,如今已经弃用;版本4-31被预留用于后续产品;版本32-255(为了区分RTMAP协议和文本协议,文本协议通常是可以打印字符)不允许使用。如果服务端无法识别客户端的版本号,应该回复版本3。客户端可以选择降低到版本3,或者终止握手过程。
包含chunk stream ID(流通道id)和chunk type(即fmt), chunk stream id 一般被简写为CSID,用来唯一标识一个特定的流通道,chunk type决定了后面的Message Header的格式。Basic Header的长度可能是1,2,或者3个字节,其中chunk type的长度是固定的(占2位,单位是bit),Basic Header的长度取决于CSID的大小,在足够存储这两个字段的前提下最好使用最少的字节从而减少由于引入Header增加的数据量。
RTMP协议支持用户自定义[3,65599] 之间的 CSID,0, 1, 2 由协议保留表示特殊信息。0 代表 Basic Header 总共要占用 2 个字节,CSID 在 [64,319] 之间; 1 代表占用 3 个字节,CSID 在 [64,65599] 之间; 2 代表该 chunk 是控制信息和一些命令信息。
包含了要发送的实际消息(可能是完整的,也可能是一部分)的描述消息。Message Header的格式和长度取决于Basic Header的chunk type,即fmt,共有四种不同的格式。其中一种格式可以表示其他三种表示的所有数据,但由于其他三种格式是基于对之前chunk的差量化的表示,因此可以更简洁地表示相同的数据,实际使用的时候还是应该采用尽量少的字节表示相同意义的数据。下面按字节从多到少的顺序分别介绍这四种格式的 Message Header。
type=0时Message Header占用11个字节,其他三种能表示的数据它都能表示,但Chunk stream的开始第一个chunk和头信息中时间戳后退(即值与上一个chunk相比减少,通常在回退播放的时候会出现这种情况)的时候必须采用这种格式。
type为1时占用7个字节,省去了表示message stream id的4个字节,表示此chunk和上一次发的chunk所在的流相同,如果在发送端和对端有一个流链接的时候可以尽量采用这种格式。
type 为 2 时占用 3 个字节,相对于 type = 1 格式又省去了表示消息长度的3个字节和表示消息类型的1个字节,表示此 chunk和上一次发送的 chunk 所在的流、消息的长度和消息的类型都相同。余下的这三个字节表示 timestamp delta,使用同type=1。
type=3时,为0字节,表示这个chunk的Message Header和上一个是完全相同的。当它跟在type=0的chunk后面时,表示和前一
个 chunk 的时间戳都是相同。什么时候连时间戳都是相同呢?就是一个 Message 拆分成多个 chunk,这个 chunk 和上一个 chunk 同属于一个 Message。而当它跟在 type = 1或 type = 2 的chunk后面时的chunk后面时,表示和前一个 chunk的时间戳的差是相同的。比如第一个 chunk 的 type = 0,timestamp = 100,第二个 chunk 的 type = 2,timestamp delta = 20,表示时间戳为 100 + 20 = 120,第三个 chunk 的 type = 3,表示 timestamp delta = 20,时间戳为 120 + 20 = 140。
在 chunk 中会有时间戳 timestamp 和时间戳差 timestamp delta,并且它们不会同时存在,只有这两者之一大于3字节能表示的最大数值 0xFFFFFF = 16777215 时,才会用这个字段来表示真正的时间戳,否则这个字段为 0。扩展时间戳占 4 个字节,
能表示的最大数值就是 0xFFFFFFFF = 4294967295。当扩展时间戳启用时,timestamp字段或者timestamp delta要全置为1,而不是减去时间戳或者时间戳差的值。
最后实际发送的chunk如下面表格所示,该表格展示了由此音频流产生的块信息。从第 3 条信息开始,数据传输达到最大优化。每条消息的头部只增加了 1 字节长度。
RTMP协议
RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种。RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。支持该协议的软件包括Adobe Media Server/Ultrant Media Server/red5等。RTMP与HTTP一样,都属于TCP/IP四层模型的应用层。(百度百科)
协议握手的过程
Client 发送 C0 和 C1 消息来启动握手过程。客户端必须接收到 S1 消息,然后发送 C2 消息。客户端必须接收到S2 消息,然后发送其他数据。服务端必须接收到 C0 或者 C1 消息,然后发送 S0 和 S1 消息。服务端必须接收到 C2 消息,然后发送其他数据。
+-------------+ +-------------+
| Client | TCP/IP Network | Server |
+-------------+ | +-------------+
| | |
Uninitialized | Uninitialized
| C0 | |
|------------------->| C0 |
| |-------------------->|
| C1 | |
|------------------->| S0 |
| |<--------------------|
| | S1 |
Version sent |<--------------------|
| S0 | |
|<-------------------| |
| S1 | |
|<-------------------| Version sent
| | C1 |
| |-------------------->|
| C2 | |
|------------------->| S2 |
| |<--------------------|
Ack sent | Ack Sent
| S2 | |
|<-------------------| |
| | C2 |
| |-------------------->|
Handshake Done | Handshake Done
| | |
Pictorial Representation of Handshake
抓包分析一下,RTMP是在TCP协议基础之上的,首先要进行TCP握手,在实际中先会发送C0+C1,然后服务端响应S0+S1+S2,然后客户端再发送C2。
通过wireshark了解到,RTMP应用层协议1537字节,版本号一个字节,数据占用1536字节。
RTMP连接的建立
论文中是这样描述的:
实际上通过协议分析,有出入。
省略了客户端向服务端发送Peer bandwidth
协议中RTMP流的创建
论文中定义创建如下,但是在Abobe实现中,通过抓包工具看出,并非如此。
推送RTMP流
进行四步操作:
1.publish 告诉服务端我要进行推流了。
2.onStatus 服务端说你开始吧。
3.客户端发送MetaData:告诉服务端我推送的流媒体的信息。
4.发送Video/Audio Data
播放RTMP流
以上是关于rtmp协议详解的主要内容,如果未能解决你的问题,请参考以下文章