RTMP使用笔记(一):解析使用wireshark抓取的RTMP协议包

一、使用ffmpeg推送RTMP流

使用以下命令用ffmpeg推流到wowza:

ffmpeg -i "D:\var\siren\event-20181227_113720723.mp4" -vcodec copy -acodec copy -f flv rtmp://192.168.154.202/live/rtsptest.stream

二、wireshark抓包筛选RTMP协议

推流过程中使用wireshark抓包,利用过滤器筛选出协议为RTMP的包
在这里插入图片描述

三、结合wireshark抓包数据讲解RTMP

1. 简介

RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing)和分包(packetizing)的问题。

Adobe的实时消息传递协议(RTMP)通过可靠的流传输提供双向消息多路复用服务,例如TCP [RFC0793],用于在一对通信对等体之间携带具有相关定时信息的视频,音频和数据消息的并行流。 实现通常为不同类别的消息分配不同的优先级,这可以影响在传输容量受限时消息被排队到基础流传输的顺序。

2. 定义

  • Payload(有效载荷):包中包含的数据,例如音频样本或压缩视频数据。
  • Packet(数据包):数据包由固定的头部和有效载荷数据组成。一些底层协议可能会要求对数据包定义封装。
  • Port(端口):“传输协议用于区分给定主机内多个目的地的抽象描述,TCP / IP协议使用小正整数识别端口。”OSI传输层使用的传输选择器(TSEL)等同于端口。
  • Transport address(传输地址):标识传输层端点的网络地址和端口的组合,例如IP地址和TCP端口。
  • Message stream(消息流):通信中消息流通的一个逻辑通道。
  • Message stream ID(消息流 ID):每条消息都有一个与之关联的ID,以标识它正在流动的消息流。
  • Chunk(块):消息的片段。在通过网络发送消息之前,消息被分成更小的部分并进行交错。这些块确保跨多个流的所有消息的按时间戳排序的端到端传送。
  • Chunk stream(块流):允许在特定方向上流动块的逻辑通信通道,块流可以从客户端传输到服务器并反向。
  • Chunk stream ID(块流ID):每个块都有一个与之关联的ID,以识别它正在流动的块流。
  • Multiplexing(合成):将单独的音频/视频数据制作成一个连贯的音频/视频流的过程,使得可以同时传输多个视频和音频。
  • DeMultiplexing(解复用):多路复用的逆过程,其中交织的音频和视频数据被组合以形成原始音频和视频数据。
  • Remote Procedure Call (RPC 远程方法调用):允许客户端或服务器在对等端调用子例程或过程的请求。
  • Metadata(元数据):有关数据的说明。 电影的元数据包括电影标题,持续时间,创建日期等。
  • Application Instance(应用实例):客户端通过发送连接请求连接的服务器上的应用程序实例。
  • Action Message Format (AMF 动作消息格式):一种紧凑的二进制格式,用于序列化ActionScript对象图。AMF有两个版本:AMF 0 [AMF0]和AMF 3 [AMF3]。

3. RTMP Chunk Stream

3.1. 消息格式

可以拆分为块以支持多路复用的消息格式取决于更高级别的协议。 但是,消息格式应该包含创建块所需的以下字段:

  • Timestamp:消息的时间戳。 该字段可以传输4个字节。
  • Length:消息有效负载的长度。 如果无法省略消息标题,则应将其包含在长度中。 该字段占用块头中的3个字节。
  • Type Id:类型ID的范围被保留用于协议控制消息。 这些传播信息的消息由RTMP Chunk Stream协议和更高级别的协议处理。 所有其他类型ID可供更高级别协议使用,并被RTMP Chunk Stream视为不透明值。 事实上,RTMP Chunk Stream中没有任何内容要求将这些值用作类型; 所有(非协议)消息可以是相同类型,或者应用程序可以使用此字段来区分同时跟踪而不是类型。 该字段在块头中占用1个字节。
  • Message Stream ID:消息流ID可以是任意值。 复用到同一块流上的不同消息流基于它们的消息流ID被多路分用。 除此之外,就RTMP Chunk Stream而言,这是一个不透明的值。该字段以小端格式占用块头中的4个字节。

3.2. 握手

RTMP连接以握手开始, 握手不同于协议的其余部分。它由三个静态大小的块组成,而不是由带有标题的可变大小的块组成。 客户端(已启动连接的端点)和服务器均发送相同的三个块。 对于展示,当客户端发送时,这些块将被指定为C0,C1和C2; S0,S1和S2由服务器发送。

3.2.1 握手顺序

  • 握手开始于客户端发送C0和C1块。
  • 在发送C2之前,客户端必须等待直到收到S1。
  • 在发送任何其他数据之前,客户端必须等待直到收到S2。
  • 在发送S0和S1之前,服务器必须等待直到收到C0,并且可以等到C1之后。 在发送S2之前,服务器必须等待直到收到C1。 在发送任何其他数据之前,服务器必须等待直到收到C2。

3.2.2 C0和S0格式

C0和S0数据包是单个八位字节,被视为单个8位整数字段:
在这里插入图片描述
以下是C0 / S0数据包中的字段:

版本(8位):在C0中,此字段标识客户端请求的RTMP版本。 在S0中,该字段标识服务器选择的RTMP版本。 此规范定义的版本为3。值0-2是早期专有产品使用的弃用值;4-31保留用于将来的实现;不允许使用32-255(允许区分RTMP与基于文本的协议,后者始终以可打印字符开头)。 无法识别客户端请求的版本的服务器应该响应3。客户端可以选择降级到版本3,或放弃握手。

3.2.2 C1和S1格式

C1和S1数据包长度为1536个八位字节,由以下字段组成:
在这里插入图片描述

  • Time (4 bytes):该字段包含一个时间戳,该时间戳应该用作从该端点发送的所有未来块的时间起点。 这可以是0,或某个任意值。 为了同步多个块流,端点可能希望发送另一个块流的时间戳的当前值。
  • Zero (4 bytes):该字段必须全为0。
  • Random data (1528 bytes):该字段可以包含任意值。 由于每个端点必须区分对其已启动的握手的响应和由其对等方发起的握手,因此该数据应该发送足够随机的内容。 但是不需要加密安全随机性,甚至动态值。

3.2.3 C2和S2格式

C2和S2数据包长1536个八位字节,几乎是S1和C1(分别)的回声,由以下字段组成:
在这里插入图片描述

  • Time (4 bytes):该字段必须包含对等体在S1(对于C2)或C1(对于S2)中发送的时间戳。
  • Time2 (4 bytes):该字段必须包含读取对等体发送的先前分组(s1或c1)的时间戳。
  • Random echo (1528 bytes):该字段必须包含对等体在S1(对于C2)或S2(对于C1)中发送的随机数据字段。 对等体可以将时间和时间2字段与当前时间戳一起用作连接的带宽和/或延迟的快速估计,但这不太可能有用。

3.2.4 握手图
在这里插入图片描述下面介绍握手图中提到的状态:

  • Uninitialized(未初始化的):协议版本在此阶段发送。 客户端和服务器都未初始化。 客户端在数据包C0中发送协议版本。 如果服务器支持该版本,它将发送S0和S1作为响应。 如果不是,则服务器通过采取适当的操作进行响应。 在RTMP中,此操作正在终止连接。
  • Version Sent(版本已发送):在未初始化状态之后,客户端和服务器都处于“已发送”状态。 客户端正在等待数据包S1,服务器正在等待数据包C1。 在接收到等待的分组时,客户端发送分组C2,并且服务器发送分组S2。 然后该状态成为Ack Sent。
  • Ack Sent(确认已发送):客户端和服务器分别等待S2和C2。
  • Handshake Done(握手完成):客户端和服务器交换消息。

3.4 分块

在握手之后,连接多路复用一个或多个块流。 每个块流携带来自一个消息流的一种类型的消息。 创建的每个块都有一个与之关联的唯一ID,称为chunk stream ID。 块通过网络传输。 在传输时,每个块必须在下一个块之前完全发送。 在接收器端,基于块流ID将块组装成消息。

分块允许将较高级别协议中的大型消息分解为较小的消息,例如,以防止较大的低优先级消息(例如视频)阻塞较小的高优先级消息(例如音频或控制)。

分块还允许以较少的开销发送小消息,因为块头包含信息的压缩表示,否则必须将其包括在消息本身中。

块大小是可配置的。 可以使用Set Chunk Size控制消息设置它。更大的块大小可以降低 CPU 开销,但在低带宽连接时因为它的大量的写入也会延迟其他内容的传递。更小的块不利于高比特率的流化。所以块的大小设置取决于具体情况。

3.4.1 块格式

每个块包含标题和数据,标题本身有三个部分:
在这里插入图片描述

  • Basic Header(基本头,1 到 3 个字节):该字段对块流ID和块类型进行编码。 块类型确定编码消息头的格式。长度完全取决于块流ID,块ID是可变长度字段。
  • Message Header(消息头,0,3,7,或者 11 个字节):该字段对有关正在发送的消息(无论是全部还是部分)的信息进行编码。 可以使用块头中指定的块类型来确定长度。
  • Extended Timestamp(扩展 timestamp,0 或 4 字节):在某些情况下,该字段存在,具体取决于块消息头中的编码时间戳或时间戳增量字段。
  • Chunk Data(块数据,可变的大小):此块的有效负载,最大为配置的最大块大小。
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值