RTMP是Real Time Messaging Protocol的简称,是基于什么时候的传输层协议上(如tcp协议)的应用层级别的协议,其设计是为了组包多媒体传输流(如视频,音频以及交互内容)前端
RTMP协议是由Adobe公司提出的一种应用层的协议,上面引述的是RTMP官方文档的introduction部分,其目的是为了给诸如视频、音频以及数据消息通讯双方提供实时的信息双向流。RTMP在实现上对不一样类型的消息实施不一样的权重,这样能够实现对当传输量受限时的底层流传输消息进行排队。git
载荷(Payload):包含在包中的数据github
包(Packet):数据包由固定头和载荷数据组成,一些底层协议可能须要对被定义包进行封装web
端口(Port):TCP/IP端口,由主机号来区分多地址segmentfault
传输地址(Transport address):网络地址和端口的组合bash
消息流(Message stream):消息流通讯的逻辑频道服务器
消息流ID(Message stream ID):每一个消息都有一个预期消息流匹配的idmarkdown
块(Chunk):消息片断。消息在被网络传输前会被分红小的部分,全部的消息会经过多路由时间序端对端传输网络
块流(Chunk stream):通讯的逻辑频道容许块以某一特定方向传送,块流能够从客户端传到服务端,也能够从服务端传回客户端并发
块流ID(Chunk stream ID):每一个块流都有一个与之匹配的id
多路复用(Multiplexing):分离的音视频数据能够连续播放的过程,使得音视频能够同时传送
多路分用(DeMultiplexing):多路复用的逆过程,能够将交错的音视频数据汇集成原始的音视频数据
远程过程调用(Remote Procedure Call):容许客户端或服务端能够调用另外一端服务端或客户端子程序或子进程的请求
元数据(Metadata):数据的描述。电影的元数据包括电影标题,时长,上映日期等等。
应用实例(Application Instance):客户端能够链接并发送链接请求的服务端实例
动做消息格式(Action Message Format):用来序列化AS(ActionScript 动做脚本)实例对象(object graphs)的压缩的二进制格式,有AMF0和AMF3两种版本
全部的整字段以字节序来传输,而且是大端排列,不作特殊说明均为十进制。时间戳以毫秒记,从0开始,32位长;时间间隔用毫秒的无符号整数表示,多是24或32位长度
尽管RTMP是被设计用来实时传输消息的,但它也能够用来处理任何消息。RTMP很是适合用于大量的音视频应用,虽然并不会提供任何优化,但却被用于更高级别的协议来进行优化,例如直播视频服务器可能会选择在客户端网速较慢的状况下丢弃视频消息而保证音频消息的实时到达。
消息格式可被分红许多块来提供多路复用,这些消息须要包括含如下字段:
字段名 | 含义 | 大小 |
---|---|---|
时间戳(Timestamp) | 消息的时间戳 | 4字节 |
长度(Length) | 消息载荷的长度,若是消息头不能被省略,须要包含长度 | 3字节 |
类型ID(Type ID) | 类型id被用于消息控制 | 1字节 |
消息流ID(Message Stream ID) | 任意数值,小端存储 | 4字节 |
RTMP握手不一样于其余协议,它包含3个固定大小的块而不是可变大小的块
开始时,客户端发送C0和C1
客户端必须在收到S1才能发送C2,收到S2才能发送任何其余数据
服务端必须等到收到C0才能发送S0和S1,而且最好能在收到C1后。服务端等到收到C1才能发送S2,服务端必须等到收到C2才能发送其余数据
C0和S0是一个8位组,被认为是一个8位整数段。对C0而言,这个字段被认为是客户端RTMP请求的版本;对S0而言,这个字段被认为是服务端选择的RTMP版本。默认是3,0-2被废弃,4-31被用于将来的版本,32-255没有被容许
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| version |
+-+-+-+-+-+-+-+-+
复制代码
C1和S1是一个1536位的长度组,包含以下字段:
字段名 | 含义 | 大小 |
---|---|---|
时间(Time) | 包含时间戳,多是0也多是任意的数值,用于时间标识 | 4字节 |
零(Zero) | 必须都是0 | 4字节 |
任意数据(Random data) | 任意数值,并不须要加密 | 1528字节 |
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| zero (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random bytes |
| (cont) |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
复制代码
C2和S2是一个1536位的长度组,对应S1和C1依次的回复,包含以下字段:
字段名 | 含义 | 大小 |
---|---|---|
时间1(Time1) | 时间戳,S1(C2发送)或C1(S2发送) | 4字节 |
时间2(Time2) | 时间戳,以前S1或C1 | 4字节 |
任意数据(Random data) | 任意数值,可快速验证链接带宽或延时 | 1528字节 |
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time2 (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| random bytes |
| (cont) |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
复制代码
未初始化阶段(Uninitialized):协议版本在这个阶段发送,客户端和服务端都是未初始化的。客户端在C0包中发送协议版本,若是服务端支持这个协议版本,其将会对应发送S0和S1;若是服务端不支持,服务端会采起合适的动做。在RTMP中,这个动做是停止链接。
版本发送阶段(Version Sent):在未初始化阶段以后客户端和服务端都处于版本发送阶段。客户端处于等待S1包,服务端处于等待C1包。在收到相应的等待的包后,客户端发送C2而服务端会发送S2,而后进入确认发送阶段。
确认发送阶段(Ack Sent):客户端和服务端响应的等待S2和C2
握手结束阶段(Handshake Done):客户端和服务端交换消息
+---------------+ +---------------+
| 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
| | |
复制代码
握手以后,链接即可以进行多路传输块流,每一个块携带着一种信息流的一种类型,每块流都有一个独一无二的id即块流id,经过网络传输,每一个块必须满载,在接收端会根据id进行从新组装。分块容许经过更高阶的协议进行小信息的分拆,好比能够经过阻止大的低优先级消息(如视频)而阻塞小的高优先级消息(如音频或控制)。分块一样也容许更少的间接消耗将小的消息进行发送,好比块头包含有表明内容的压缩信息,也可能反过来包含在信息之中。块的大小是可配置的,大的块可减小CPU使用,可是却可能因为较多的写操做而带来其余内容低带宽的延迟,小的块不适合高比特流的传输,块的大小在每一个方向上独立保持。
每一个块包含头和数据,头包含三部分:
字段名 | 含义 | 大小 |
---|---|---|
基础头(Basic Header) | 块流id和块类型 | 1或3字节 |
消息头(Message Header) | 消息的主要内容 | 0,3,7或11字节 |
扩展时间戳(Extended Timestamp) | 某种情境下的时间戳 | 0或4字节 |
块数据(Chunk Data) | 块的载荷 | 可变字节 |
+---------------+----------------+--------------------+----------------+
| Basic Header | Message Header | Extended Timestamp | Chunk Data |
+---------------+----------------+--------------------+----------------+
| |
| <------------------ Chunk Header -----------------> |
Chunk Format
复制代码
1.块基本头
有三种类型:
字段名 | 含义 | 大小 |
---|---|---|
块流id(cs id) | 数值2~63 | 6位 |
格式(fmt) | 格式标识 | 2位 |
块流id-64(cs id - 64) | 数值减去64 | 8或16位 |
块基础头1:
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|fmt| cs id |
+-+-+-+-+-+-+-+-+
复制代码
块基础头2:
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|fmt| 0 | cs id - 64 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
复制代码
块基础头3:
0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|fmt| 1 | cs id - 64 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
复制代码
2.块消息头
有四种类型:
Type 0:11字节
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp | message length| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message length (cont) |message type id| msg stream id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message stream id (cont) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk Message Header - Type 0 复制代码
Type 1:7字节
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp delta | message length| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message length (cont) |message type id| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk Message Header - Type 1 复制代码
Type 2:3字节
0 1 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp delta |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Chunk Message Header - Type 2
复制代码
Type 3:没有头
公共头字段:
字段名 | 含义 | 大小 |
---|---|---|
事件戳间隔(timestamp delta) | 类型1或类型2 | 3字节 |
消息长度(message length) | 类型0或类型1 | 3字节 |
消息类型id(message type id) | 类型0或类型1 | 1字节 |
消息流id(message stream id) | 类型0 | 4字节 |
3.扩展时间戳
当时间戳大于 16777215(0xFFFFFF)时使用
消息类型ID为1,2,3,5,6是协议控制消息,这些内容须要块流协议作基础
用于提示设置最大字节,最大128字节,服务端和客户端能够修改这个值,并升级另外一端的大小
用于提示等待完成消息,以后丢弃部分接收的消息
当接收字节和视窗大小相同时,客户端或服务端必须发送给对应端确认消息
当进行确认时,客户端或服务端发送给对应端视窗大小
客户端和服务端向对应端发送输出限制
RTMP可用各类传输层协议
消息能够包含音频,视频,数据以及其余消息格式
1.消息头
包含消息类型,长度,时间戳,消息流id
2.消息载荷
实际消息承载内容
消息类型为4
客户端和服务端的消息相互操做
1.命令消息
AMF0格式值为20 AMF3格式值为17
2.数据消息
AMF0格式值为18 AMF3格式值为15
3.共享对象消息
AMF0格式值为19 AMF3格式值为16
4.音频消息
值为8
5.视频消息
值为9
6.聚合消息
值为22
7.用户控制消息事件
1.网络链接命令
链接 调用 建立流
2.网络流命令
播放 播放2 删除流 接收音频 接收视频 发布 寻址 暂停