RTMP是Real Time Messaging Protocol的简称,是基于什么时候的传输层协议上(如tcp协议)的应用层级别的协议,其设计是为了组包多媒体传输流(如视频,音频以及交互内容)前端
RTMP协议是由Adobe公司提出的一种应用层的协议,上面引述的是RTMP官方文档的introduction部分,其目的是为了给诸如视频、音频以及数据消息通讯双方提供实时的信息双向流。RTMP在实现上对不一样类型的消息实施不一样的权重,这样能够实现对当传输量受限时的底层流传输消息进行排队。git
全部的整字段以字节序来传输,而且是大端排列,不作特殊说明均为十进制。时间戳以毫秒记,从0开始,32位长;时间间隔用毫秒的无符号整数表示,多是24或32位长度github
尽管RTMP是被设计用来实时传输消息的,但它也能够用来处理任何消息。RTMP很是适合用于大量的音视频应用,虽然并不会提供任何优化,但却被用于更高级别的协议来进行优化,例如直播视频服务器可能会选择在客户端网速较慢的状况下丢弃视频消息而保证音频消息的实时到达。web
消息格式可被分红许多块来提供多路复用,这些消息须要包括含如下字段:segmentfault
字段名 | 含义 | 大小 |
---|---|---|
时间戳(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才能发送其余数据dom
C0和S0是一个8位组,被认为是一个8位整数段。对C0而言,这个字段被认为是客户端RTMP请求的版本;对S0而言,这个字段被认为是服务端选择的RTMP版本。默认是3,0-2被废弃,4-31被用于将来的版本,32-255没有被容许tcp
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) | | .... | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+---------------+ +---------------+ | 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 删除流 接收音频 接收视频 发布 寻址 暂停