流媒体协议——RTMP实时消息传输协议详解

RTMP——Real Time Messaging Protocol(实时消息传输协议)

RTMP是由Adobe公司提出的,在互联网TCP/IP五层体系结构中应用层,RTMP协议是基于TCP协议的,也就是说RTMP实际上是使用TCP作为传输协议。TCP协议在处在传输层,是面向连接的协议,能够为数据的传输提供可靠保障,因此数据在网络上传输不会出现丢包的情况。不过这种可靠的保障也会造成一些问题,也就是说前面的数据包没有交付到目的地,后面的数据也无法进行传输。幸运的是,目前的网络带宽基本上可以满足RTMP协议传输普通质量视频的要求。

RTMP传输的数据的基本单元为Message,但是实际上传输的最小单元是Chunk(消息块),因为RTMP协议为了提升传输速度,在传输数据的时候,会把Message拆分开来,形成更小的块,这些块就是Chunk。

RTMP块流作为一款高级多媒体流协议提供了流的多路复用和打包服务。RTMP块流被设计用来传输实时消息协议,它可以使用任何协议来发送消息流。每个消息都包含时间戳和有效类型标识。RTMP块流和RTMP适用于各种视听传播的应用程序,包括一对一的,和一对多的视频直播、点播服务、互动会议应用程序。

当使用一个可靠的传输协议如TCP[RFC0793]时,RTMP块流提供了一种可以在多个流中,基于时间戳的端到端交付所有消息的方法。

RTMP块流不仅包含了自己的协议控制信息,同时也提供了一个更高级别的协议机制,用来嵌入用户控制信息。

消息(Message)的结构

消息是RTMP协议中基本的数据单元。不同种类的消息包含不同的Message Type ID,代表不同的功能。RTMP协议中一共规定了十多种消息类型,分别发挥着不同的作用。例如,Message Type ID在1-7的消息用于协议控制,这些消息一般是RTMP协议自身管理要使用的消息,用户一般情况下无需操作其中的数据。Message Type ID为8,9的消息分别用于传输音频和视频数据。Message Type ID为15-20的消息用于发送AMF编码的命令,负责用户与服务器之间的交互,比如播放,暂停等等。消息首部(Message Header)有四部分组成:标志消息类型的Message Type ID,标志消息长度的Payload Length,标识时间戳的Timestamp,标识消息所属媒体流的Stream ID

Message结构分析

1.Message Type:它是一个消息类型的ID,通过该ID接收方可以判断接收到的数据的类型,从而做相应的处理。Message Type ID在1-7的消息用于协议控制,这些消息一般是RTMP协议自身管理要使用的消息,用户一般情况下无需操作其中的数据。Message Type ID为8,9的消息分别用于传输音频和视频数据。Message Type ID为15-20的消息用于发送AMF编码的命令,负责用户与服务器之间的交互,比如播放,暂停等。

2.Playload Length: 消息负载的长度,即音视频相关信息的的数据长度,4个字节

3.TimeStamp:时间戳,3个字节。

4.Stream ID:消息的唯一标识。拆分消息成Chunk时添加该ID,从而在还原时根据该ID识别Chunk属于哪个消息。

5.Message Body:消息体,承载了音视频等信息。

 

消息块(Chunk)

在网络上传输数据时,消息需要被拆分成较小的数据块,才适合在相应的网络环境上传输。RTMP协议中规定,消息在网络上传输时被拆分成消息块(Chunk)。消息块首部(Chunk Header)有三部分组成:用于标识本块的Chunk Basic Header,用于标识本块负载所属消息的Chunk Message Header,以及当时间戳溢出时才出现的Extended Timestamp。

通过上图可以看出,消息块在结构上与与消息类似,有Header和Body。

1.Basic Header:基本的头部信息,在头部信息里面包含了chunk stream ID(流通道Id,用来标识指定的通道)和chunk type(chunk的类型)。

2.Message Header:消息的头部信息,包含了要发送的实际信息(可能是完整的,也可能是一部分)的描述信息。Message Header的格式和长度取决于Basic Header的chunk type。

3.Extended TimeStamp:扩展时间戳。

4.Chunk Data:块数据。

RTMP在传输数据的时候,发送端会把需要传输的媒体数据封装成消息,然后把消息拆分成消息块,再一个一个进行传输。接收端收到消息块后,根据Message Stream ID重新将消息块进行组装、组合成消息,再解除该消息的封装处理就可以还原出媒体数据。由此可以看出,RTMP收发数据是以Chunk为单位,而不是以Message为单位。需要注意的是,RTMP发送Chunk必须是一个一个发送,后面的Chunk必须等前面的Chunk发送完成。

消息分块

在消息被分割成几个消息块的过程中,消息负载部分(Message Body)被分割成大小固定的数据块(默认是128字节,最后一个数据块可以小于该固定长度),并在其首部加上消息块首部(Chunk Header),就组成了相应的消息块。消息分块过程如下图所示,一个大小为307字节的消息被分割成128字节的消息块(除了最后一个)。

RTMP传输媒体数据的过程中,发送端首先把媒体数据封装成消息,然后把消息分割成消息块,最后将分割后的消息块通过TCP协议发送出去。接收端在通过TCP协议收到数据后,首先把消息块重新组合成消息,然后通过对消息进行解封装处理就可以恢复出媒体数据。

RTMP协议握手

rtmp 连接从握手开始。它包含三个固定大小的块。客户端发送的三个块命名为 C0,C1,C2;服务端发送的三个块命名为
S0,S1,S2。

握手序列:

  1. 握手开始时,客户端将发送C0,C1 chunk,此时客户端必须等待,直到收到S1 chunk,才能发送C2 chunk。
  2. 此时服务端必须等待,直到已收到C0后才能发送S0和S1,当然也可能会等到接收C1后才发送。
  3. 当服务器收到C2后才能再发送的其他数据,同理,当客户端收到S2后才能发送其它数据。
+-------------+                           +-------------+
|    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协议中,此动作是中止连接。
注: 在”C0和S0格式”章节中提及,如果服务器不支持客户端的版本号,可以选择降到版本3或中止。

发送版本
客户端和服务器双方在未初始化状态后,会进入发送版本状态。之后,客户端等待S1包,服务器等待C1包。待接收到数据包,客户端发送C2包,服务器发送S2包。然后,双方都进入答复状态。客户端等待C2的答复,服务器等待S2的答复。

握手完成
客户端和服务器交换消息。



 

参考:https://blog.csdn.net/xiangzhihong8/article/details/68560237

https://www.jianshu.com/p/c04d810b7562

https://blog.csdn.net/ilv_xj/article/details/79054013

 

你可能感兴趣的:(网络技术)