RTMP协议

背景介绍

RTMP(Real Time Messaging Protocol) 是由 Adobe 公司基于 Flash Player 播放器对应的音视频 flv 封装格式提出的一种,基于TCP 的数据传输协议。本身具有稳定、兼容性强、高穿透的特点。常被应用于流媒体直播、点播等场景。常用于推流方(主播)的稳定传输需求。RTMP协议的默认端口号是1935

RTMP流程

握手

RTMP是基于TCP的,在RTMP之前,传输层的TCP连接就已经建立好了。但除此之外,应用层的RTMP协议也是需要再建立RTMP连接的。

在建立连接之前,要经过RTMP握手。握手的主要目的为:交换RMTP协议版本信息、确立连通性、设置通信的起始时间等。握手的大致流程如下图所示:

在这里插入图片描述

建立连接

在握手成功之后,就可以正式建立连接了,大致流程如下:

在这里插入图片描述

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

创建流

建立连接后,就可以创建流了,大致流程如下:

在这里插入图片描述

  1. 客户端发送命令“创建流”给服务器
  2. 服务器接收到命令之后,发送“结果”给客户端。

推流或拉流

推流:(publish命令)

在这里插入图片描述

拉流:(play命令)

在这里插入图片描述

抓包分析

以推流为例,下图是RTMP推流的抓包分析

在这里插入图片描述

RTMP数据格式

RTMP Message

Message是RTMP协议中的基本数据单元。消息可以包含音频,视频,控制消息,以及其它数据。RTMP的消息由两部分构成,分别是header和payload。payload表示有效载荷。其中header的格式如下:

在这里插入图片描述

chunk分块

RTMP 协议为了维持稳定连续传递,避免单次传输数据量问题,采用了传输层封包,数据流切片的实现形式。被用来对当前带宽进行划分和复用的最小传输单位,被称为 Chunk 即消息块。通常情况下,一个Message,如果数据量超出当前 Chunk Size 的话,则会被拆分成多个chunk分块来分批传输。通过指定首个 Chunk 和后续 Chunk 类型,以及 Chunk Header 其他标志性数据,来使当前被切割的消息,能够在对端得到有效的还原和执行。可以参考下图来理解:

在这里插入图片描述

也就是说,除了RTMP握手期间的报文,其余的任何RTMP报文都是以chunk为单位进行发送的。

Chunk Header

和大多数协议一样,RTMP协议也是经典的 header+body 格式,详见下图:

在这里插入图片描述

ChunkData部分没什么好说的,就是携带的音视频数据或者协议的命令数据等,本文主要介绍的是ChunkHeader部分。

Chunk Header主要由三部分构成:BasicHeader + MessageHeader + ExtendedTimestamp

Basic Header

基础数据头(BasicHeader)有单字节、二字节、三字节这三种版本,但不论是哪一个版本,前两个比特位都固定为fmt字段,用以指示chunk message header的格式类型

RTMP 规格将BasicHeader分为3种:ID 在 2~63 范围内的 1-Byte 版;ID 在 64~319 范围内的 2-Byte 版;ID 在 64~65599 范围内的 3-Byte 版。基础数据头组成,也包含三个部分。

单字节格式:

在这里插入图片描述

二字节和三字节格式:

在这里插入图片描述

其中cs_id( Chunk stream ID )的范围 3 - 65599,0、1、2被保留。也就是说,如果第一个字节的后6位大于2,则表示是单字节模式,如果为0就表示二字节模式,为1就表示三字节模式。

需要注意的是,cs_id是用来区分消息信道的。因为 RTMP 协议,所有的通信都是通过同一个 TCP socket 来完成的,因此所有类型的通信信道需要由来进行区分,从而判断当前收到的消息所属的信道类型。也就是说,并不能通过cs_id来区分是音频还是视频。

MessageHeader

MessageHeader的有4种格式,由BasicHeader的fmt字段决定,
MessageHeader的有4种格式,由BasicHeader的fmt字段决定,具体如下所示:

  • Type 0:Full Header,这是最完整的头部格式,包含了所有的必要信息
    类型0块头的长度是 11 个字节。这一类型必须用在块流的起始位置,和流 timestamp 重来的时候
    在这里插入图片描述
  • Type 1:Full Header without Timestamp,与完整头部类似,但省略了时间戳字段
    类型1块头长为 7 个字节。不包含消息流 ID;这一块使用前一块一样的流 ID。可变长度消息的流 (例如,一些视频格式) 应该在第一块之后使用这一格式表示之后的每个新消息。
    在这里插入图片描述
  • Type 2:Message Stream ID Only,仅含消息流ID的头部
    类型2块头长度为 3 个字节。既不包含流 ID 也不包含消息长度;这一块具有和前一块相同的流 ID 和消息长度。具有不变长度的消息 (例如,一些音频和数据格式) 应该在第一块之后使用这一格式表示之后的每个新消息。
    在这里插入图片描述
  • Type 3:Type Only,最简化的头部形式,只包含了一个字节的类型标识符
    类型3的块没有消息头。流 ID、消息长度以及 timestamp delta 等字段都不存在;这种类型的块使用前面块一样的块流 ID。当单一一个消息被分割为多块时,除了第一块的其他块都应该使用这种类型。组成流的消息具有同样的大小,流 ID 和时间间隔应该在类型 2 之后的所有块都使用这一类型。如果第一个消息和第二个消息之间的 delta 和第一个消息的 timestamp 一样的话,那么在类型 0 的块之后要紧跟一个类型 3 的块,因为无需再来一个类型 2 的块来注册 delta 了。如果一个类型 3 的块跟着一个类型 0 的块,那么这个类型 3 块的 timestamp delta 和类型 0 块的 timestamp 是一样的。

对于这些Type,这里有一张便于理解的图:

在这里插入图片描述

块消息头中各字段的描述如下:

  • timestamp(3字节):时间戳,一般是绝对时间戳。
  • timestamp delta (3字节):对于一个类型 1 或者类型 2 的块,前一块的 timestamp 和当前块的 timestamp 的区别在这里发送。如果 delta 大于或者等于 16777215 (十六进制 0xFFFFFF),那么这一字段必须是为 16777215,表示具有扩展 timestamp 字段来对整个 32 位 delta 进行编码。否则的话,这一字段应该是为具体 delta。
  • message length (3字节):对于一个类型 0 或者类型 1 的块,消息长度在这里进行发送。注意这通常不同于块的有效载荷的长度。块的有效载荷代表所有的除了最后一块的最大块大小,以及剩余的 (也可能是小消息的整个长度) 最后一块。
  • message type id (消息类型,1字节):对于类型 0 或者类型 1 的块,消息的类型在这里发送。
  • message stream id (4字节):对于一个类型为 0 的块,保存消息流 ID。消息流 ID 以小端格式保存。所有同一个块流下的消息都来自同一个消息流。当可以将不同的消息流组合进同一个块流时,这种方法比头压缩的做法要好。但是,当一个消息流被关闭而其他的随后另一个是打开着的,就没有理由将现有块流以发送一个新的类型 0 的块进行复用了。

不同的消息类型对应不同的数据,类型说明如下:

在这里插入图片描述

ExtendedTimestamp

这个字段比较好理解,当MessageHeader中的timestamp字段的大小不够用时,即当其值为0xFFFFFF时,才会设置ExtendedTimestamp,否则就没有这个字段。

参考官方文档的说明:

扩展 timestamp 字段用于对大于 16777215 (0xFFFFFF) 的 timestamp 或者 timestamp delta 进行编码;也就是,对于不适合于在 24 位的类型 0、1 和 2 的块里的 timestamp 和 timestamp delta 编码。这一字段包含了整个 32 位的 timestamp 或者 timestamp delta 编码。可以通过设置类型 0 块的 timestamp 字段、类型 1 或者 2 块的 timestamp delta 字段 16777215 (0xFFFFFF) 来启用这一字段。当最近的具有同一块流的类型 0、1 或 2 块指示扩展 timestamp 字段出现时,这一字段才会在类型为 3 的块中出现。

内容补充

RTMP URL的格式

RTMP的url格式为:rtmp://server_address/application_instance_name/[stream_key]

  • server_address 是 RTMP 服务器的地址,可以是 IP 地址或域名。
  • application_instance_name 是应用实例的名称,例如 “live” 或 “vod”(视频点播)。
  • [stream_key] 是可选的,代表特定的流键,通常用于标识不同的直播流。

例如有一个 RTMP 服务器位于 rtmp.example.com,该服务器上有一个名为 “live” 的实例,用于处理直播流。如果要创建一个名为 “myStream” 的直播流,那么对应的RTMP URL为:rtmp://rtmp.example.com/live/myStream

ChunkStreamID、MessageTypeID、MessageStreamID的区别

  1. ChunkStreamID是用于区分不同信道的,官方并没有规定哪种信道具体要用什么ID,这完全是由用户自定义的,所以在不同的场景下同一种流的ChunkStreamID可能会不同。

  2. MessageTypeID则是专门用于区分消息类型的,官方有规定的具体ID与Type之间的对应细则。

  3. MessageStreamID则是为特定的消息流提供唯一的标识。当客户端与服务器之间有多个并发的消息流时,MessageStreamID帮助区分这些不同的流。例如,在多路复用的情况下,同一个连接上可以同时传输多个音轨或视频轨道,每个都会有一个独立的MessageStreamID。

简单来说,这三者之间并不存在强关联,仅仅作为不同信息层区分使用。

绝对时间戳和相对时间戳

RTMP的时间戳有绝对时间戳和相对时间戳之分,如果fmt为0,则第一个字段为timestamp,这就表示的是绝对时间戳。如果fmt不为零,那么其它格式的第一个字段都为timestamp delta,表示相对时间戳(时间戳差),表示相对于前一个绝对时间戳的差值。

官方文档

想要了解更多细节,可以参考官方文档:

  1. RTMP 协议规范(中文版) - 仲达超 - 博客园
  2. RTMP官方文档 - 英文原版

本文参考

  1. 流媒体:RTMP 协议完全解析 - 知乎
  2. RTMP 协议规范(中文版) - 仲达超 - 博客园
  3. RTMP协议推流交互流程 - 靑い空゛ - 博客园
  4. FFmpeg学习(八)RTMP与FLV协议 - 山上有风景 - 博客园
  5. RTMP协议学习——Message与Chunk解读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479163.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络----基本概念

基本概念 在这一章从整体上介绍计算机网络的概况, 为后续的学习搭建起整体的框架; 介绍计算机网络中的基础术语和概念; 什么是因特网 『 因特网 』是一个世界范围内互联了数以亿计的计算设备的计算机网络; 因特网具体构成 因特网互联了数以亿计的计算设备, 这些设备被称为…

CKA认证 | Day4 K8s管理应用生命周期(下)

第四章 K8s管理应用程序生命周期(下) 1、Pod对象 1.1 Pod 的基本概念 Pod 是 Kubernetes 中最基本和最重要的概念之一,是一个逻辑抽象概念,Kubernetes创建和管理的最小单元, 一个Pod由一个容器或多个容器组成。它简…

【微服务】Nacos

一、安装 1、官网地址:https://nacos.io/download/nacos-server/ 2、启动:找到bin目录下的startup.cmd双击启动,或者打开一个命令窗口输入: startup.cmd -m standalone双击启动后如下:可以访问控制台地址 访问后的…

学习笔记032——Spring学习笔记

文章目录 一、Spring开发步骤二、Spring配置文件1、Bean标签基本配置2、Bean标签范围配置3、Bean生命周期配置4、Bean实例化三种方式5、Bean的依赖注入概念6、Bean的依赖注入方式【第一种:set方法注入】【第二种:构造方法注入】 7、Bean的依赖注入的数据…

某科技研发公司培训开发体系设计项目成功案例纪实

某科技研发公司培训开发体系设计项目成功案例纪实 ——建立分层分类的培训体系,加强培训跟踪考核,促进培训成果实现 【客户行业】科技研发行业 【问题类型】培训开发体系 【客户背景】 某智能科技研发公司是一家专注于智能科技、计算机软件技术开发与…

Elasticsearch:Retrievers 介绍

检索器(retrievers)是 Elasticsearch 中搜索 API 中添加的新抽象层。它们提供了在单个 _search API 调用中配置多阶段检索管道的便利。此架构通过消除对复杂搜索查询的多个 Elasticsearch API 调用的需求,简化了应用程序中的搜索逻辑。它还减…

Python学习34天

import random class Game: peo0 rob0 # # def __init__(self,peo,rob): # self.peopeo # self.robrob def Play(self): """ 石头剪刀布游戏,0代表石头,1代见到,2代表石头 …

hive的存储格式

1) 四种存储格式 hive的存储格式分为两大类:一类纯文本文件,一类是二进制文件存储。 Hive支持的存储数据的格式主要有:TEXTFILE、SEQUENCEFILE、ORC、PARQUET 第一类:纯文本文件存储 textfile: 纯文本文件存储格式…

solr 远程命令执行 (CVE-2019-17558)

目录 漏洞描述 执行漏洞py脚本,取得shell连接 EXP 漏洞描述 Apache Velocity是一个基于Java的模板引擎,它提供了一个模板语言去引用由Java代码定义的对象。Velocity是Apache基金会旗下的一个开源软件项目,旨在确保Web应用程序在表示层和业…

uname -m(machine) 命令用于显示当前系统的机器硬件架构(Unix Name)

文章目录 关于 arm64 架构检查是否安装了 Rosetta 2其他相关信息解释:命令功能:示例: dgqdgqdeMac-mini / % uname -m arm64您运行的 uname -m 命令显示您的系统架构是 arm64。这意味着您的 Mac Mini 使用的是 Apple 的 M1 或更新的芯片&…

实现在两台宿主机下的docker container 中实现多机器通讯

基于我的实验背景 上位机:ubuntu 20.04 (docker humble 22.04) 下位机:ubuntu 22.04(docker noetic 20.04) 目标:实现在上位机中的docker container 容器的22.04环境去成功远程访问 非同网段的下位机的20.04的contai…

(计算机组成原理)期末复习

第一章 计算机的基本组成:硬件软件(程序)计算机系统 软件有系统软件(系统管理工具),应用软件 计算机硬件:包括主机和外设,主机包括CPU和内存,***CPU由运算器和控制器所组…

QML TableView 实例演示 + 可能遇到的一些问题(Qt_6_5_3)

一、可能遇到的一些问题 Q1:如何禁用拖动? 在TableView下加一句代码即可: interactive: false 补充:这个属性并不专属于TableView,而是一个通用属性。很多Controls下的控件都可以使用,其主要作用就是控…

【vue3实现微信小程序】从轮播图到公告栏的前端开发之旅

快速跳转: 我的个人博客主页👉:Reuuse博客 新开专栏👉:Vue3专栏 参考文献👉:uniapp官网 免费图标👉:阿里巴巴矢量图标库 ❀ 感谢支持!☀ 前情提要 &#x…

【大数据学习 | Spark-Core】RDD的缓存(cache and checkpoint)

1. 单应用缓存:cache 1.1 cache算子 cache算子能够缓存中间结果数据到各个executor中,后续的任务如果需要这部分数据就可以直接使用避免大量的重复执行和运算。 rdd 存储级别中默认使用的算子cache算子,cache算子的底层调用的是persist算子…

网络安全风险评估

项目背景 随着信息化技术的快速发展,特别是面向社会、政府机构、企业等业务系统的投入使用,各组织机构对网络和信息系统安全防护都提出了新的要求。为满足安全需求,需对组织机构的网络和信息系统的安全进行一次系统全面的评估,以…

Selenium 自动化测试demo

场景描述: 模拟用户登录页面操作,包括输入用户名、密码、验证码。验证码为算数运算,如下: 使用到的工具和依赖: 1. Selenium:pip install selenium 2. 需要安装浏览器驱动:这里使用的是Edge 3…

架构-微服务架构

文章目录 前言一、系统架构演变1. 单体应用架构2. 垂直应用架构3. 分布式架构4. SOA 架构5. 微服务架构 二. 微服务架构介绍1. 微服务架构的常见问题2. 微服务架构的常见概念3. 微服务架构的常见解决方案4. 解决方案选型 三. Spring Cloud Alibaba介绍1. 主要功能2. 组件 前言 …

unity | 动画模块之卡片堆叠切换

一、预览动画 可以放很多图,可以自己往后加,可以调图片x轴和y轴间距,可以调图片飞出方向,可以调堆叠方向。 图1 图片堆叠动画预览 二、纯净代码 有粉丝问我这个效果,最近很忙,没有时间细写,先…

Burp入门(2)-代理功能介绍

声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址:burp功能介绍(1)_哔哩哔哩_bilibili 本文详细介绍burp的代理功能。 一、插件配置代理 1. 安装代理插件(Goog…