目录
- 1. RTMP消息类型
- 1.1 协议控制消息
- 1.1.1 设置块大小(SetChunkSize,message type id = 1)
- 1.1.2 中断消息(AbortMessage ,message type id = 2 )
- 1.1.3 应答消息(Acknowledgement ,message type id = 3)
- 1.1.4 窗口确认大小(Window Acknowledgement Size,message type id = 5)
- 1.1.5 设置流带宽(SetPeerBandwidth,message type id = 6)
- 1.2 用户控制消息
- 1.3 不同消息类型
- 1.3.1 命令消息(Command Message, message type id = 17 or 20)
- 1.3.1.1 NetConnection命令
- 1.3.1.1.1 connect
- 1.3.1.1.2 call
- 1.3.1.1.3 createStream
- 1.3.1.2 NetStream命令
- 1.3.1.2.1 play
- 1.3.1.2.2 play2
- 1.3.1.2.3 deleteStream
- 1.3.1.2.4 receiveAudio
- 1.3.1.2.5 receiveVideo
- 1.3.1.2.6 publish
- 1.3.1.2.7 seek
- 1.3.1.2.8 pause
- 1.3.2 数据消息(Data Message, message type id = 18 or 15)
- 1.3.3 共享对象消息(Shared Object Message, message type id = 19 or 16)
- 1.3.4 音频消息(Audio Data, message type id = 8)
- 1.3.5 视频消息(Video Data, message type id = 9)
- 1.3.6 聚合消息(Aggregate Message, message type id = 22)
- 2.小结
RTMP相关记录:
【流媒体】RTMP协议概述
【流媒体】RTMP协议的数据格式
不得不说RTMP协议比之前看到的RTP协议要复杂很多,其中涉及到的数据格式和控制方式要更多。前面记录了RTMP协议的主要流程和数据格式,本文记录RTMP中的消息类型,不同的消息类型决定当前的数据包完成不同的任务,因此是极其重要的内容
1. RTMP消息类型
RTMP协议中有不同的消息类型,用于完成数据传输或命令控制等操作,这些消息类型写在message type id当中
1.1 协议控制消息
RTMP 块流使用message type ID为1、2、3、5 和 6 用于协议控制消息,协议控制消息的message stream id必须为0,以表示这是用于控制流程的消息,cs_id必须为2,以标识这是一个用于传输控制消息的特殊 CSID
1.1.1 设置块大小(SetChunkSize,message type id = 1)
RTMP在网络传输的基本数据载体是chunk,发送端需要先与接收端确认数据包的大小,这样接收端才能正确的解析数据包。实际使用时,双端的chunk size是独立的,例如client端使用的chunk size为128,server在接收和解析时按照128字节来进行,同时,server端使用的chunk size可以为130,client在接收和解析时按照130字节来进行
如果message type id为1,message payload当中存储的是所配置的chunk size,共4字节,第1个比特必须为0,后面31个字节存储的是期望的chunk size,这个chunk size最小不得小于128比特
1.1.2 中断消息(AbortMessage ,message type id = 2 )
当一个message被切分为多个chunk,接受端只接收到了部分chunk时,发送该控制消息表示发送端不再传输同message的chunk,接受端接收到这个消息后要丢弃这些不完整的chunk
如果message type id为2,message payload当中存储的是要丢弃其当前消息的块流ID,用4字节表示
1.1.3 应答消息(Acknowledgement ,message type id = 3)
客户端或者服务器在接收到等同于窗口大小的字节之后必须要发送给对端一个确认。窗口大小是指发送者在没有收到接收者确认之前发送的最大数量的字节。这个消息定义了序列号,也就是目前接收到的字节数
如果message type id为3,message payload当中存储的是收到的字节数,用4字节表示
1.1.4 窗口确认大小(Window Acknowledgement Size,message type id = 5)
这条命令设置了一个消息窗口大小,当发送端发送了窗口大小字节之后期待对端的确认,接收端在接收到窗口大小字节之后给发送端一个反馈到发送端。这个消息窗口大小的发送方可以是客户端或者服务器端。
如果message type id为5,message payload中存储的是窗口确认大小,用4字节表示
1.1.5 设置流带宽(SetPeerBandwidth,message type id = 6)
客户端或者服务器端发送这一消息来限制其对端的输出带宽。对端接收到这一消息后,将通过限制这一消息中窗口大小指出的已发送但未被答复的数据的数量以限制其输出带宽。接收到这一消息的对端应该回复一个窗口确认大小消息,如果这个窗口大小不同于其发送给 (设置对端带宽) 发送者的最后一条消息
如果message type id为6,message payload共有5个字节,前4个字节存储的是限制带宽的大小,后1个字节是限制的类型。其中限制的类型为:
(1)Limit type = 0 (Hard Limit)
硬限制,对端应该限制其输出带宽到指示的窗口大小
(2)Limit type = 1 (Soft Limit)
对端应该限制其输出带宽到知识的窗口大小,或者已经有限制在其作用的话就取两者之间的较小值
(3)Limit type = 2(Dynamic Limit)
如果先前的限制类型为 Hard,处理这个消息就好像它被标记为 Hard,否则的话忽略这个消息
1.2 用户控制消息
RTMP 使用消息类型 ID 4 表示用户控制消息,即message stream id = 4,同时cs_id应为2。用户控制消息一旦被接收立马生效,这类消息的timestamp是被忽略的。
发送端发出这个消息来通知对端,下面我要发送用户操作事件。这一消息携带有事件类型和事件数据。前两个字节用于指示事件类型,随后是事件数据,并且这个事件数据字段的大小是可变的。如果消息必须通过 RTMP 块流层传输时,最大块大小应该足够大,使得这些消息能够放到一个块当中一起发送
下面展示了用户控制事件的类型:
事件 (Event) | 描述 |
---|---|
StreamBegin (=0) | server发送给client,一个流已就绪并可以用来通信。默认情况下,这一事件在成功接收到客户端的应用连接命令之后以 ID 0 发送。数据长度为4字节,标识已就绪流的流 ID |
StreamEOF (=1) | server发送给client,请求的流的回放数据已经结束。在发送额外的命令之前不再发送任何数据。client将丢弃接收到的这个流的消息。数据长度为4字节,标识回放已结束的流的流 ID |
StreamDry (=2) | server发送给client,当前流中已没有数据。当server在一段时间内没有检测到任何消息,它可以通知相关客户端当前流已经没数据了。数据长度为4字节,标识已没数据的流的流 ID |
SetBufferLength (=3) | client发送给server,用于缓存流中任何数据的缓存大小 (以毫秒为单位)。这一事件在server开始处理流之前就发送。数据的前4个字节代表了流ID,后4个字节代表了以毫秒为单位的缓存的长度 |
StreamIsRecorded (=4) | server发送给client,当前流是一个录制流。数据长度为4字节,标识录制流的流 ID |
PingRequest (=6) | server发送给client,用于测试是否能够将数据送达client。数据是为一个4字节的timestamp,标识server发送这一命令时server的本地时间。client在接收到这一消息后会立即发送 PingResponse 回复 |
PingResponse (=7) | client作为对ping请求的回复发送这一事件到server。数据是为一个4字节的 timestamp,这个timestamp来自于server发送的PingRequest中的timestamp |
1.3 不同消息类型
1.3.1 命令消息(Command Message, message type id = 17 or 20)
命令消息在client和server之间传递 AMF 编码的命令。如果message type id为20,则进行AMF0编码;如果message type id为17,则进行AMF3编码。这些消息发送之后可以进行的操作包括,连接,流创建,发布,播放,暂停等。一个命令消息由命令名、事务ID 和包含相关参数的命令对象组成。
以下类的对象用于发送不同的命令:
(1)NetConnection 代表上层的服务器端和客户端之间连接的一个对象
(2)NetStream 一个代表发送音频流、视频流和其他相关数据的通道的对象。当然,我们也会发送控制数据流的命令,诸如 play、pause 等等
1.3.1.1 NetConnection命令
NetConnection 管理着一个客户端应用和服务器端之间的双相连接。此外,它还提供远程方法的异步调用。NetConnection 可以发送以下命令:
(1)connect
(2)call
(3)close
(4)createStream
1.3.1.1.1 connect
connect命令的使用,client会发送connect命令到server,请求连接到一个server app
由客户端发送connect到server命令结构如下:
字段名 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置给 “connect” |
Transaction ID | Number | 永远设置为1 |
Command Object | Object | 具有名称-值对的命令信息对象 |
Optional User Arguments | Object | 任意可选信息 |
下面是connect命令的命令对象中使用的名称-值对的描述
属性 | 类型 | 描述 | 举例 |
---|---|---|---|
app | String | client连接到的server应用程序名称 | testapp |
flashver | String | Flash Player 版本号,与ApplicationScript getversion() 方法返回的是同一个字符串 | FMSc/1.0 |
swfUrl | String | 进行连接的源SWF文件的URL | file://c:/FlvPlayer.swf |
tcUrl | String | server URL,具有以下格式:protocol://servername:port/appName/appInstance | rtmp://localhost:1935/testapp/instance1 |
fpad | Boolean | 如果使用了代理,则设置为True | true或false |
audioCodecs | Number | 表明客户端所支持的音频编码 | SUPPORT_SND_MP3 |
videoCodecs | Number | 表明所支持的视频编码 | SUPPORT_VID_SORENSON |
videoFunction | Number | 表示支持哪些特殊视频功能 | SUPPORT_VID_CLIENT_SEEK |
pageUrl | String | 加载SWF文件的网页的Url | http://somehost/sample.html |
object Encoding | Number | AMF编码方法 | AMF3 |
audioCodecs属性的标志值如下
类型 | 描述 | 值 |
---|---|---|
SUPPORT_SND_NONE | 原始数据,未压缩 | 0x0001 |
SUPPORT_SND_ADPCM | ADPCM压缩 | 0x0002 |
SUPPORT_SND_MP3 | mp3压缩 | 0x0004 |
SUPPORT_SND_INTEL | 未使用 | 0x0008 |
SUPPORT_SND_UNUSED | 未使用 | 0x0010 |
SUPPORT_SND_NELLY8 | NellyMoser在8-kHz的压缩 | 0x0020 |
SUPPORT_SND_NELLY | NellyMoser压缩 (5, 11, 22, 和44kHz) | 0x0040 |
SUPPORT_SND_G711A | G711A压缩 (Flash Media Server Only) | 0x0080 |
SUPPORT_SND_G711U | G711U压缩 (Flash Media Server Only) | 0x0100 |
SUPPORT_SND_NELLY16 | NellyMoser在16-kHz的压缩 | 0x0200 |
SUPPORT_SND_AAC | 高级音频编码 (AAC) | 0x0400 |
SUPPORT_SND_SPEEX | speex音频 | 0x0800 |
SUPPORT_SND_ALL | 所有RTMP支持的音频编解码器 | 0x0FFF |
videoCodecs属性的标志值如下
类型 | 描述 | 值 |
---|---|---|
SUPPORT_VID_UNUSED | 不再使用 (obsolete value) | 0x0001 |
SUPPORT_VID_JPEG | 不再使用 (obsolete value) | 0x0002 |
SUPPORT_VID_SORENSON | Sorenson Flash Video | 0x0004 |
SUPPORT_VID_HOMEBREW | V1 screen sharing | 0x0008 |
SUPPORT_VID_VP6 (On2) | On2 video (Flash 8+) | 0x0010 |
SUPPORT_VID_VP6ALPHA (On2 with alpha channel) | On2 video with alpha channel | 0x0020 |
SUPPORT_VID_HOMEBREW (screensharing v2) | Screen sharing version 2 (Flash 8+) | 0x0040 |
SUPPORT_VID_H264 | H264 video | 0x0080 |
SUPPORT_VID_ALL | 所有RTMP支持的视频编解码器 | 0x00FF |
videoFunction属性的标志值如下
类型 | 描述 | 值 |
---|---|---|
SUPPORT_VID_CLIENT_SEEK | 表示客户端可以执行帧精确查找 | 1 |
objectEncoding属性的标志值如下
类型 | 描述 | 值 |
---|---|---|
AMF0 | flash 6及以后版本支持的AMF0对象编码 | 0 |
AMF3 | AMF3编码从flash 9 (AS3) | 3 |
从server到client的命令结构如下所示
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | _result或_error;描述返回的是结果还是错误 |
Transaction ID | Number | 连接响应的事务id为1 |
Properties | Object | 描述连接属性(fmsver等)的名称-值对 |
Information | Object | 描述server响应的名称-值对, “code”、“level”、"description"是这些信息中为数不多的名称 |
1.3.1.1.2 call
NetConnection对象的调用方法在接收端运行远程过程调用(RPC)。被调用的RPC名称作为参数传递给调用命令。
从发送方到接收方的命令结构如下
字段 | 类型 | 描述 |
---|---|---|
Procedure Name | String | 被调用的远程过程的名称 |
Transaction ID | Number | 如果期望得到响应,设置一个事务Id,否则设置为0 |
Command Object | Object | 如果存在一些命令信息要设置这个对象,否则置空 |
Optional Arguments | Object | 要提供的任何可选参数 |
返回信息的命令结构如下
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令名称 |
Transaction ID | Number | 响应所属的命令Id |
Command Object | Object | 如果存在一些命令信息要设置这个对象,否则置空 |
Response | Object | 被调用的方法的响应 |
1.3.1.1.3 createStream
client将此命令发送到server以创建用于消息通信的逻辑通道,音频、视频和元数据的发布通过使用createStream命令创建的流通道进行。netConnection是默认的通信通道,其流ID为0。协议和一些命令消息(包括createStream)使用默认通信通道
从client到server的命令结构如下所示
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令名称,设置为 “createStream” |
Transaction ID | Number | 命令的事物ID |
Command Object | Object | 如果存在一些命令信息要设置这个对象,否则置空 |
从server到client的命令结构如下所示
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | _result 或 _error;表示返回的值是result或error |
Transaction ID | Number | 响应所属的命令ID |
Command Object | Object | 如果存在一些命令信息要设置这个对象,否则置空 |
Stream ID | Number | 返回值要么是一个流 ID 要么是一个错误信息对象 |
1.3.1.2 NetStream命令
NetStream定义了一个通道,通过这个通道,流音频、视频和数据消息可以在连接客户端和服务器的NetConnection上流动。一个NetConnection对象可以为多个数据流支持多个NetStream
client可以在NetStream上向服务器发送以下命令:
(1)play
(2)play2
(3)deleteStream
(4)closeStream
(5)receiveAudio
(6)receiveVideo
(7)publish
(8)seek
(9)pause
server使用“onStatus”命令向client发送NetStream状态更新
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令名称 “onStatus” |
Transaction ID | Number | 事务ID设置为0 |
Command Object | Null | 没有onStatus消息的命令对象 |
Info Object | Object | 一个 AMF 对象至少要有以下三个属性。“level” (String):这一消息的等级,“warning”、“status”、“error” 中的某个值;“code” (String):消息码,例如 “NetStream.Play.Start”;“description” (String):人类可读的消息描述 |
1.3.1.2.1 play
client将此命令发送到server以播放流。也可以使用此命令多次创建播放列表。如果想创建一个动态的播放列表,在不同的直播或录播流之间切换,调用play不止一次,并立即传递指定的流,清除排队等待播放的任何其他流,为重置传递true
client到server的命令结构如下:
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “play” |
Transaction ID | Number | 事物ID设置为0 |
Command Object | Null | 命令信息不存在。设置为空类型 |
Stream Name | String | 要播放流的名字。要播放视频 (FLV) 文件,使用没有文件扩展名的名字对流名进行定义 (例如,“sample”)。要重播 MP3 或者 ID3,你必须在流名前加上 mp3:例如,“mp3:sample”。要播放 H.264/AAC 文件,你必须在流名前加上 mp4:并指定文件扩展名。例如,要播放 sample.m4v 文件,定义 “mp4:sample.m4v” |
Start | Number | 一个可选的参数,以秒为单位定义开始时间。默认值为 -2,表示用户首先尝试播放流名字段中定义的直播流。如果那个名字的直播流没有找到,它将播放同名的录制流。如果没有那个名字的录制流,客户端将等待一个新的那个名字的直播流,并当其有效时进行播放。如果你在 Start 字段中传递 -1,那么就只播放流名中定义的那个名字的直播流。如果你在 Start 字段中传递 0 或一个整数,那么将从 Start 字段定义的时间开始播放流名中定义的那个录制流。如果没有找到录制流,那么将播放播放列表中的下一项 |
Duration | Number | 一个可选的参数,以秒为单位定义了回放的持续时间。默认值为 -1。-1 值意味着一个直播流会一直播放直到它不再可用或者一个录制流一直播放直到结束。如果你传递 0 值,它将只播放单一一帧,因为播放时间已经在录制流的开始的 Start 字段指定了。假定定义在 Start 字段中的值大于或者等于 0。如果你传递一个正数,将播放 Duration 字段定义的一段直播流。之后,变为可播放状态,或者播放 Duration 字段定义的一段录制流。(如果流在 Duration 字段定义的时间段内结束,那么流结束时回放结束)。如果你在 Duration 字段中传递一个 -1 以外的负数的话,它将把你给的值当做 -1 处理 |
Reset | Boolean | 一个可选的布尔值或者数字定义了是否对以前的播放列表进行 flush |
1.3.1.2.2 play2
与play命令不同,play2可以切换到不同的比特率流,而无需改变播放内容的时间轴。服务器为客户端可以在play2中请求的所有支持的比特率维护多个文件
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令名,设置为 “play2” |
Transaction ID | Number | 事物ID,设置为0 |
Command Object | Null | 命令信息不存在,设置为 null 类型 |
Parameters | Object | 一个 AMF 编码的对象,该对象的属性是为公开的 flash.net.NetStreamPlayOptions ActionScript 对象所描述的属性 |
1.3.1.2.3 deleteStream
当NetStream对象被销毁时,NetStream发送deleteStream命令
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “deleteStream” |
Transaction ID | Number | 事务ID设置为0 |
Command Object | Null | 命令信息对象不存在。设置为空类型 |
Stream ID | Number | 在server上销毁的流的ID |
server不会发送任何反馈
1.3.1.2.4 receiveAudio
NetStream发送receiveAudio消息来通知server是否将音频发送到client。从client到server的命令结构如下所示
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “receiveAudio” |
Transaction ID | Number | 事务ID设置为0 |
Command Object | Null | 命令信息对象不存在。设置为空类型 |
Bool Flag | Boolean | True或false表示是否接收音频 |
如果发送receiveAudio命令时将bool标志设置为false,则服务器不发送任何响应。如果这个标志被设置为true,服务器响应状态消息NetStream.Seek.notify和NetStream.play.Start
1.3.1.2.5 receiveVideo
NetStream发送receiveVideo消息来通知服务器是否将视频发送给客户端。client到server的命令结构如下:
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “receiveVideo” |
Transaction ID | Number | 事务ID设置为0 |
Command Object | Null | 命令信息对象不存在。设置为空类型 |
Bool Flag | Boolean | True或false表示是否接收视频 |
如果发送receiveVideo命令时将bool标志设置为false,则服务器不发送任何响应。如果这个标志被设置为true,服务器响应状态消息NetStream.Seek.Notify和NetStream.Play.Start
1.3.1.2.6 publish
client发送publish命令将命名流发布到server。使用此名称,任何client都可以播放此流并接收发布的音频、视频和数据消息。client到server的命令结构如下
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “publish” |
Transaction ID | Number | 事务ID设置为0 |
Command Object | Null | 命令信息对象不存在,设置为 null 类型 |
Publishing Name | String | 发布的流的名字 |
Publishing Type | String | 发布类型。可以设置为 “live”、“record” 或者 “append”。record:流被发布,数据被录制到一个新的文件。新文件被存储在服务器上包含服务应用目录的子路径。如果文件已存在,将重写。append:流被发布,数据被添加到一个文件。如果该文件没找着,将新建一个。live:直播数据只被发布,并不对其进行录制 |
服务器用onStatus命令响应以标记发布的开始
1.3.1.2.7 seek
client发送seek命令来查找媒体文件或播放列表中的偏移量(以毫秒为单位)。client到server的命令结构如下:
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “seek” |
Transaction ID | Number | 事务ID设置为0 |
Command Object | Null | 该命令没有命令信息对象。设置为空类型 |
milliSeconds | Number | 搜索到播放列表的毫秒数 |
当seek成功时,服务器发送一个状态消息NetStream.Seek.Notify。如果失败,则返回_error消息
1.3.1.2.8 pause
client发送pause命令来告诉server暂停或开始播放
字段 | 类型 | 描述 |
---|---|---|
Command Name | String | 命令的名称,设置为 “pause” |
Transaction ID | Number | 没有这一命令的事务 ID,设为 0 |
Command Object | Null | 命令信息对象不存在,设置为空类型 |
Pause/Unpause Flag | Boolean | 为true或false,表示暂停或恢复播放 |
milliSeconds | Number | 流暂停或恢复播放的毫秒数。这是流暂停时客户端的当前流时间。当回放恢复时,服务器将只发送时间戳大于此值的消息 |
当流暂停时,服务器发送一个状态消息NetStream.Pause.Notify。NetStream.Unpause.Notify在流处于未暂停状态时发送。如果失败,则返回_error消息
1.3.2 数据消息(Data Message, message type id = 18 or 15)
client或者server通过发送数据消息,以发送元数据或者任何用户数据到对端。元数据包括数据 (音频,视频等等) 的详细信息,如创建时间,时长,主题等等。如果message type id为18,则进行AMF0编码;如果message type id为15,则进行AMF3编码
1.3.3 共享对象消息(Shared Object Message, message type id = 19 or 16)
共享对象是一个 Flash 对象 (一个value和key的集合),这个对象在多个不同客户端、应用实例中保持同步。如果message type id为19,则使用AMF0编码;如果message type id为16,则使用AMF3编码。每个消息可以包含有不同的事件
事件类型的列表如下
事件 (Event) | 描述 |
---|---|
Use (=1) | client发送这给server,表明一个已命名的共享对象已创建 |
Release (=2) | 当共享对象在client被删除时,client发送这一事件到server |
Request Change (=3) | client发送这一事件,请求更改与共享对象的命名参数关联的值 |
Change (=4) | 如果请求被接受,server将发送此事件给请求的client,以响应RequestChange事件,即指定参数值的更改 |
Success (=5) | 如果请求被接受,server发送这一事件给请求的client,以作为 RequestChange 事件的响应 |
SendMessage (=6) | client将此事件发送到server以广播消息。在接收到此事件时,server向所有client广播一条消息,包括发送方 |
Status (=7) | server发送这一事件以通知client异常情况 |
Clear (=8) | server向client发送此事件以清除共享对象。server还发送此事件以响应client在连接时发送的事件 |
Remove (=9) | server发送此事件以让client删除插槽 |
Request Remove (=10) | client发送此事件以使client删除槽 |
Use Success (=11) | 在连接成功时,server将此事件发送给client |
1.3.4 音频消息(Audio Data, message type id = 8)
client或者server发送这一消息以发送音频数据到对端,message type id为8
1.3.5 视频消息(Video Data, message type id = 9)
client或者server发送这一消息以发送视频数据到对端,message type id为9
1.3.6 聚合消息(Aggregate Message, message type id = 22)
聚合消息是一条消息,它包含了一系列子RTMP信息,message type id为22。
聚合消息中的message stream id会覆盖其中包含的一系列子消息的message stream id。聚合消息的timestamp与第1个子消息之间的差异是用于将子消息的timestamp重新规范化为流时间刻度的偏移量。偏移量被添加到每个子消息的时间戳中。第一个子消息的时间戳应该与聚合消息的时间戳相同,因此偏移量应该为零
上面这句话的意思是,聚合消息中子信息的timestamp是有一个偏移量的,并且越后面的子消息偏移量越大(相对于第1个子消息)
使用统计消息具有以下性能优势:
(1)将多个消息融合到一个块中,这样通过适当的增加块大小,可以减少块发送的数量
(2)子消息可以在内存中连续存储。在网络中系统调用发送这些数据时更高效
2.小结
RTMP消息类型比较多,我理解其中主体可以分成3部分:
(1)RTMP协议默认使用的控制消息
(2)用户可配置的控制消息
(3)用户可配置的命令消息、数据消息等
后续需要关注一下代码当中(参考RTMPdump)是如何实现这些操作的