- RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议。
- RTMP协议基于TCP协议,依靠TCP协议提供可靠的数据传输,因此数据在网络上传输不会出现丢包的情况。
- RTMP协议连接可靠,多路复用,延时容易受到网络状态的影响。
引用一段很多地方都能看到的话,
握手、消息块概念
握手的目的是为了确认对端RTMP的Version和确认对端能互相通信。
消息块就是消息的载体,是RTMP协议最重要的载体,这个载体是有一定格式的,如果把Client和Server端当作铁路的两个站点,那这个消息块就是火车,它负责运输货物。正如火车有火车头、车厢一样,消息块也有基本头,消息头和消息负载。
RTMP协议当中,除了握手协议,其他的数据都是以消息块的方式发送的,发送一个消息时,当块大小比需要发送的消息的字节数更大时,一个消息块就相当于一个消息,否则消息需要分成多个消息块。
握手
RTMP的握手分为简单握手和复杂握手。
简单握手
要建立一个可靠的RTMP connection,首先需要Client和Server两者通过协议进行握手操作。基本的简单握手流程有以下几个流程:
+-+-+-+-+-+-+ +-+-+-+-+-+-+
| Client | | Server |
+-+-+-+-+-+-+ +-+-+-+-+-+-+
|-------- C0 C1 -------->|
|<------ S0 S1 S2 -------|
|--------- C2 ---------->|
握手是一切的开始,Client和Server两个站点之前要运输货物,首先得先互相通知对方,确认铁轨是否符合火车运行,是否畅通无阻,是否能准确的运输货物到对端。
客户端要向服务器发送C0,C1,C2(按序)三个chunk,服务器向客户端发送S0,S1,S2(按序)三个chunk,然后才能进行有效的信息传输。RTMP协议本身并没有规定这6个Message的具体传输顺序,但RTMP协议的实现者需要保证这几点如下:
- 客户端要等收到S1之后才能发送C2
- 客户端要等收到S2之后才能发送其他信息(控制信息和真实音视频等数据)
- 服务端要等到收到C0之后发送S1
- 服务端必须等到收到C1之后才能发送S2
- 服务端必须等到收到C2之后才能发送其他信息(控制信息和真实音视频等数据)
实际的流程大概是这样的:
- Client发送带有1byte的C0和固定长度为1536byte的C1;
- Server发送S0S1S2给Client;
- Client发送C2。
C0和S0的格式
+-+-+-+-+-+-+-+-+
| version |
+-+-+-+-+-+-+-+-+
1字节,Client端和Server端使用的RTMP版本。
C1和S1的格式
+-+-+-+-+-+-+-+-+-+-+
| time (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| zero (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| random bytes |
+-+-+-+-+-+-+-+-+-+-+
|random bytes(cont) |
| .... |
+-+-+-+-+-+-+-+-+-+-+
共1536个字节。
- time: 4 字节
本字段包含时间戳。该时间戳应该是发送这个数据块的端点的后续块的时间起始点。
可以是 0 ,或其他的任何值。为了同步多个流,端点可能发送其块流的当前值。 - zero: 4 字节
本字段必须是全零。 - random bytes: 1528 字节。
本字段可以包含任何值。终端需要区分出响应来自它发起的握手还是对端发起的握手,这个数据应该发送一些足够随机的数。这个不需要对随机数进行加密保护,也不需要动态值。
C2和S2的格式
+-+-+-+-+-+-+-+-+-+-+
| time (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| time2(4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| random bytes |
+-+-+-+-+-+-+-+-+-+-+
|random bytes(cont) |
| .... |
+-+-+-+-+-+-+-+-+-+-+
- time: 4 字节
本字段必须包含对等段发送的时间,即:如果当前是C2,需要截取S1发过来的时间戳; 如果当前是S2,需要截取C1发过来的时间戳; - time2 : 4 字节
本字段必须包含先前发送的并被对端读取的包的时间戳。可以再取当前时间戳,和C1或者S1当时取时间戳的方式一样。 - random bytes: 1528 字节
本字段必须包含对端发送的随机数据字段,即:如果当前是C2,需要截取S1发过来的随机字段; 如果当前是S2,需要截取C1发过来的随机字段。
复杂握手
+-------------+ +-------------+
| 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
[译]握手示意图