RTMP 协议从属于应用层,被设计用来在适合的传输协议(如 TCP)上复用和打包多媒体传输流(如音频、视频和互动内容)。RTMP 提供了一套全双工的可靠的多路复用消息服务,类似于 TCP 协议 [RFC0793],用来在一对结点之间并行传输带时间戳的音频流,视频流,数据流。通常情况下,不同类型的消息会被分配不同的优先级,当网络传输能力受限时,优先级用来控制消息在网络底层的排队顺序。
实时消息传递协议块流 (RTMP 块流)。它作为一款高级多媒体流协议提供了流的多路复用和打包服务。RTMP 块流被设计用来传输实时消息协议,它可以使用任何协议来发送消息流。每个消息都包含时间戳和有效类型标识。RTMP 块流和 RTMP 适用于各种视听传播的应用程序,包括一对一的,和一对多的视频直播、点播服务、互动会议应用程序。
当使用一个可靠的传输协议如 TCP[RFC0793] 时,RTMP 块流提供了一种可以在多个流中,基于时间戳的端到端交付所有消息的方法。RTMP 块流不提供任何优先级或类似形式的控制,但可以使用更高级别的协议来提供这样的优先级。例如,一个视频服务器可以根据发送的时间或确认每个消息的时间,来决定为一个网络差的用户丢弃视频信息,以确保音频信息的及时接收。
RTMP 块流不仅包含了自己的协议控制信息,同时也提供了一个更高级别的协议机制,用来嵌入用户控制信息。
消息格式可以被分割成多个块,用来在更高的协议中支持多路复用。在创建块消息格式时,应该包含以下字段:
时间戳
消息的时间戳。这个字段占用 4 字节。
长度
消息的有效长度。如果消息头不能被忽略,它应该包括长度。这个字段在块头中占用 3 字节。
类型 ID
各种类型的协议控制消息的 ID。这些消息使用 RTMP 块流协议和更高级别的协议来传输信息。所有其他类型的 ID 可以用在高级协议,这对于 RTMP 块流来说,是不透明的。事实上,RTMP 块流中没有要求使用这些值作为类型;所有 (无协议的) 消息可能是相同的类型,或者应用程序使用这个字段来区分多个连接,而不是类型。这个字段在块头中占用 1 字节。
消息流 ID
消息流 ID 可以是任意值。当同一个块流被复用到不同的消息流中时,可以通过消息流 ID 来区分它们。另外,对于 RTMP 块流而言,这是一个不透明值。该字段占用 4 字节,使用小端序。
RTMP 连接从握手开始。它包含三个固定大小的块,不像其他的协议,是由头部大小可变的块组成的。
客户端(初始化连接的一端)和服务端发送同样的三个块。为了方便描述,客户端发送的三个块命名为 C0,C1,C2;服务端发送的三个块命名为 S0,S1,S2。
客户端通过发送 C0 和 C1 消息来启动握手过程。客户端必须接收到 S1 消息,然后发送 C2 消息。客户端必须接收到 S2 消息,然后发送其他数据。
服务端必须接收到 C0 或者 C1 消息,然后发送 S0 和 S1 消息。服务端必须接收到 C1 消息,然后发送 S2 消息。服务端必须接收到 C2 消息,然后发送其他数据。
C0 和 S0 包由一个字节组成,下面是 C0/S0 包内的字段:
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- | version |
- +-+-+-+-+-+-+-+-+
- C0 and S0 bits
版本 (8 比特)
在 C0 包内,这个字段代表客户端请求的 RTMP 版本号。在 S0 包内,这个字段代表服务端选择的 RTMP 版本号。此文档使用的版本是 3。版本 0-2 用在早期的产品中,现在已经被弃用;版本 4-31 被预留用于后续产品;版本 32-255(为了区分 RTMP 协议和文本协议,文本协议通常以可打印字符开始)不允许使用。如果服务器无法识别客户端的版本号,应该回复版本 3。客户端可以选择降低到版本 3,或者中止握手过程。
C1 和 S1 包长度为 1536 字节,包含以下字段:
- 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) |
- | .... |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- C1 and S1 bits
时间 (4 字节)
本字段包含一个时间戳,客户端应该使用此字段来标识所有流块的时刻。时间戳取值可以为零或其他任意值。为了同步多个块流,客户端可能希望多个块流使用相同的时间戳。
零 (4 字节)
本字段必须为零。
随机数据 (1528 字节)
本字段可以包含任意数据。由于握手的双方需要区分另一端,此字段填充的数据必须足够随机 (以防止与其他握手端混淆)。不过没必要为此使用加密数据或动态数据。
C2 和 S2 包长度为 1536 字节,作为 C1 和 S1 的回应,包含以下字段:
- 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 echo |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | random echo |
- | (cont) |
- | .... |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- C2 and S2 bits
时间 (4 字节)
本字段必须包含对端发送的时间戳。
时间 (4 字节)
本字段必须包含时间戳,取值为接收对端发送过来的握手包的时刻。
随机数据 (1528 字节)
本字段必须包含对端发送过来的随机数据。握手的双方可以使用时间 1 和时间 2 字段来估算网络连接的带宽和 / 或延迟,但是不一定有用。
- +-------------+ +-------------+
- | 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
- 握手示意图
下面是握手示意图中提到的状态:
未初始化
协议版本号在此阶段发送。客户端和服务器均处于未初始化状态。客户端发送携带协议版本号的 C0 包。如果服务器支持此版本,回复 S0 和 S1 包。如果服务器不支持此版本,使用适当的动作回复。在 RTMP 协议中,此动作是中止连接。
发送版本
客户端和服务器双方在未初始化状态后,会进入发送版本状态。之后,客户端等待 S1 包,服务器等待 C1 包。待接收到数据包,客户端发送 C2 包,服务器发送 S2 包。然后,双方都进入答复状态。客户端等待 C2 的答复,服务器等待 S2 的答复。
握手完成
客户端和服务器交换消息。
来源: http://www.cnblogs.com/renhui/p/6641244.html