美文网首页RTMP
RTMP协议相关知识

RTMP协议相关知识

作者: 孔雨露 | 来源:发表于2019-08-10 08:52 被阅读0次

    @TOC

    1. RTMP协议简介

    RTMP协议是一个互联网TCP/IP五层体系结构中应用层的协议。RTMP协议中基本的数据单元称为消息(Message)。当RTMP协议在互联网中传输数据的时候,消息会被拆分成更小的单元,称为消息块(Chunk)。RTMP 是目前主流的流媒体传输协议,广泛用于直播领域,可以说市面上绝大多数的直播产品都采用了这个协议。
    RTMP协议就像一个用来装数据包的容器,这些数据可以是AMF格式的数据,也可以是FLV中的视/音频数据。一个单一的连接可以通过不同的通道传输多路网络流。这些通道中的包都是按照固定大小的包传输的。

    • 优点
    1. CDN 支持良好,主流的 CDN 厂商都支持
    2. 协议简单,在各平台上实现容易
    • 缺点
    1. 基于 TCP ,传输成本高,在弱网环境丢包率高的情况下问题显著
    2. 不支持浏览器推送
    3. Adobe 私有协议,Adobe 已经不再更新

    2. RTMP协议基本概念

    2.1 消息相关概念

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

    2.1.1 消息

    消息是RTMP协议中基本的数据单元。不同种类的消息包含不同的Message Type ID,代表不同的功能。RTMP协议中一共规定了十多种消息类型,分别发挥着不同的作用。

    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 Type:它是一个消息类型的ID,通过该ID接收方可以判断接收到的数据的类型,从而做相应的处理。Message Type ID在1-7的消息用于协议控制,这些消息一般是RTMP协议自身管理要使用的消息,用户一般情况下无需操作其中的数据。
    • Message Type ID为8,9的消息分别用于传输音频和视频数据。Message Type ID为15-20的消息用于发送AMF编码的命令,负责用户与服务器之间的交互,比如播放,暂停等。
    • Playload Length: 消息负载的长度,即音视频相关信息的的数据长度,4个字节
    • TimeStamp:时间戳,3个字节。
    • Stream ID:消息的唯一标识。拆分消息成Chunk时添加该ID,从而在还原时根据该ID识别Chunk属于哪个消息。
    • Message Body:消息体,承载了音视频等信息。

    2.1.2. 消息块

    在网络上传输数据时,消息需要被拆分成较小的数据块,才适合在相应的网络环境上传输。RTMP协议中规定,消息在网络上传输时被拆分成消息块(Chunk)。
    消息块首部(Chunk Header)有三部分组成:

    • 用于标识本块的Chunk Basic Header
    • 用于标识本块负载所属消息的Chunk Message Header
    • 以及当时间戳溢出时才出现的Extended Timestamp
    在这里插入图片描述
    在这里插入图片描述

    通过上图可以看出,消息块在结构上与与消息类似,有Header和Body。
    下面对图的每个部分简要介绍:

    • Basic Header:基本的头部信息,在头部信息里面包含了chunk stream ID(流通道Id,用来标识指定的通道)和chunk type(chunk的类型)。
    • Message Header:消息的头部信息,包含了要发送的实际信息(可能是完整的,也可能是一部分)的描述信息。Message Header的格式和长度取决于Basic Header的chunk type。
    • Extended TimeStamp:扩展时间戳。
    • Chunk Data:块数据。

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

    2.1.3. 消息分块

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

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

    在这里插入图片描述

    2.2. RTMP中的逻辑结构

    RTMP协议规定,播放一个流媒体有两个前提步骤

    第一步,建立一个网络连接(NetConnection)
    第二步,建立一个网络流(NetStream)。

    其中,网络连接代表服务器端应用程序和客户端之间基础的连通关系。网络流代表了发送多媒体数据的通道。服务器和客户端之间只能建立一个网络连接,但是基于该连接可以创建很多网络流。他们的关系如图所示:

    在这里插入图片描述

    2.5.

    2.6.

    2.7.

    3. RTMP协议流程

    总的流程图如下:


    在这里插入图片描述

    3.1. 连接流程

    播放一个RTMP协议的流媒体需要经过以下几个步骤:

    • 握手
    • 建立连接
    • 建立流
    • 播放

    RTMP连接都是以握手作为开始的。建立连接阶段用于建立客户端与服务器之间的“网络连接”;建立流阶段用于建立客户端与服务器之间的“网络流”;播放阶段用于传输视音频数据。

    下面来详细分析一下这几个过程都做了一些什么东东

    3.1.1.握手

    在rtmp连接建立后,服务端与客户端需要通过3次交换报文完成握手,握手其他的协议不同,是由三个静态大小的块,而不是可变大小的块组成的,客户端与服务器发送相同的三个chunk,客户端发送c0,c1,c2,服务端发送s0,s1,s2。

    • 发送规则

    握手开始于客户端发送 C0,C1 块。
    在发送 C2 之前客户端必须等待接收 S1 。
    在发送任何数据之前客户端必须等待接收 S2。
    服务端在发送 S0 和 S1 之前必须等待接收 C0,也可以等待接收 C1。
    服务端在发送 S2 之前必须等待接收 C1。
    服务端在发送任何数据之前必须等待接收 C2。

    • 数据格式

    C0与S0

    C0和S0的长度是一个字节,在 S0 中这个字段表示服务器选择的 RTMP 版本。rtmp1.0规范所定义的版本是 3;0-2 是早期产品所用的,已被丢弃;4-31保留在未来使用;32-255 不允许使用(为了区分其他以某一字符开始的文本协议)。如果服务无法识别客户端请求的版本,应该返回 3 。客户端可以选择减到版本 3 或选择取消握手。

    C1与S1

    C1 和 S1 有 1536 字节长,由下列字段组成:
    时间:4 字节 本字段包含时间戳。该时间戳应该是发送这个数据块的端点的后续块的时间起始点。可以是 0,* 或其他的 任何值。为了同步多个流,端点可能发送其块流的当前值。
    零:4 字节 本字段必须是全零。
    随机数据:1528 字节。 本字段可以包含任何值。 因为每个端点必须用自己初始化的握手和对端初始化的握 手来区分身份,所以这个数据应有充分的随机性。但是并不需要加密安全的随机值,或者动态值

    C2与S2

    C2 和 S2 消息有 1536 字节长。只是 S1 和 C1 的回复。本消息由下列字段组成。
    时间:4 字节 本字段必须包含对等段发送的时间(对 C2 来说是 S1,对 S2 来说是 C1)。
    时间 2:4 字节 本字段必须包含先前发送的并被对端读取的包的时间戳。
    随机回复:1528 字节 本字段必须包含对端发送的随机数据字段(对 C2 来说是 S1,对 S2 来说是 C1) 。 每个对等端可以用时间和时间 2 字段中的时间戳来快速地估计带宽和延迟。 但这样做可 能并不实用。
    RTMP握手的这个过程就是完成了两件事:1. 校验客户端和服务器端RTMP协议版本号,2. 是发了一堆数据,猜想应该是测试一下网络状况,看看有没有传错或者不能传的情况。

    • 流程图如下


      在这里插入图片描述

    3.1.2. 建立网络连接

    • 流程图如下:


      在这里插入图片描述

    下面对建立网络连接的流程简单介绍

    1. 客户端发送命令消息中的“连接”(connect)到服务器,请求与一个服务应用实例建立连接。
    2. 服务器接收到连接命令消息后,发送确认窗口大小(Window Acknowledgement Size)协议消息到客户端,同时连接到连接命令中提到的应用程序。
    3. 服务器发送设置带宽()协议消息到客户端。
    4. 客户端处理设置带宽协议消息后,发送确认窗口大小(Window Acknowledgement Size)协议消息到服务器端。
    5. 服务器发送用户控制消息中的“流开始”(Stream Begin)消息到客户端。
    6. 服务器发送命令消息中的“结果”(_result),通知客户端连接的状态。

    注意

    这里面的connect 命令消息,命令里面包含什么东西,协议中没有说,真实通信中要指定一些编解码的信息,这些信息是以AMF格式发送的, 其中audioCodecs和videoCodecs这两个指定音视频编码信息的不能少的。

    Window Acknowledgement Size 是设置接收端消息窗口大小,一般是2500000字节,即告诉客户端你在收到我设置的窗口大小的这么多数据之后给我返回一个ACK消息,告诉我你收到了这么多消息。在实际做推流的时候推流端要接收很少的服务器数据,远远到达不了窗口大小,所以基本不用考虑这点。而对于服务器返回的ACK消息一般也不做处理,我们默认服务器都已经收到了这么多消息。
    服务器返回的_result命令类型消息的payload length一般不会大于128字节,但是在最新的nginx-rtmp中返回的消息长度会大于128字节,所以一定要做好收包,组包的工作。

    3.1.3. 建立网络流

    • 建立网络流过程简述
      创建完网络连接之后就可以创建网络流了

    过程如下

    1. 客户端发送命令消息中releaseStream命令到服务器端
    2. 客户端发送命令消息中FCPublish命令到服务器端
    3. 客户端发送命令消息中的“创建流”(createStream)命令到服务器端。
    4. 服务器端接收到“创建流”命令后,发送命令消息中的“结果”(_result),通知客户端流的状态。

    注意:解析服务器返回的消息会得到一个stream ID, 这个ID也就是以后和服务器通信的 message stream ID, 一般返回的是1,不固定。

    • 流程图如下:


      在这里插入图片描述

    3.1.4. 播放流

    图如下:


    在这里插入图片描述

    相关文章

      网友评论

        本文标题:RTMP协议相关知识

        本文链接:https://www.haomeiwen.com/subject/neyljctx.html