RTMP:Real Time Messaging Protocol 实时消息传送协议
字节序:大端
Message Format:
Timestamp:4 bytes
Length:3 bytes
Type ID:1 bytes
Message Stream ID:4 bytes 小端
Handshake
three static_sized chunks
client:C0 C1 C2
server:S0 S1 S2
simple handshake:
handshake sequence
握手开始于客户端发送C0、C1块
客户端在发送C2块之前必须等待直到S1块被接收
客户端在发送任何其他数据之前必须等待直到S2块被接收
服务器在发送S0、S1之前必须等待直到C0被接收或是C1被接收服务器在发送S2之前必须等待直到C1被接收
服务器在发送任何其他数据之前必须等待直到C2被接收
C0和S0格式
一个字节(8bits)
本版本是3
C1和S1格式
1536个字节
C2和S2格式
1536个字节,是C1和S1的回复响应
time:必须包含对等段发送的时间戳(对C2来说是S1,对S2来说是C1)time2:必须包含先前发送的被对端读取的包(S1或C1)的时间戳
handshake diagram
Complete handshake
Chunking
Chunk format
A header and data
+--------------+----------------+--------------------+----------+ | Basic Header | Message Header | Extended Timestamp | Chunk Data| +--------------+----------------+--------------------+----------+ | |
|<------------------- Chunk Header ----------------->|
Chunk Format
Basic header:1-3bytes,chunk stream ID and chunk type(fmt) 长度可变type depend on the format of the encoded message header
the length depend on the chunk stream ID
ID:3-65599,0\1\2 reserved
0:2bytes,ID range 64-319 (the second byte+64)
1:3bytes,ID range 64-65599(the third byte*256+the second byte+64)
2:low-level protocol
2-63:
64-319:
64-65599:
Cs id:6bits 表示2-63的块流ID,0和1表示本字段2或3字节版本
Fmt:2bits 表示4种types
Cs id-64:块流ID-64的值
Message header:0, 3, 7, or 11 bytes ,长度取决于chunk type(fmt)four different formats
Type 0:11bytes,块流开始和时间戳返回时必须有这种块
Timestamp:3bytes,消息的绝对时间戳在这里发送。如果时间戳大于或等于
16777215(16进制0x00ffffff),该值必须为16777215,并且扩展时间戳
必须出现。
Message length:3bytes,数据大小
Message type id:1bytes,数据类型
Message stream id:4bytes,流ID
Message type:
Type 1:7bytes,具有可变大小消息的流(many video
formats),在第一个消息之后的每个消息的第一个块应该使用这个格式。
Type 2:3bytes,具有固定大小消息的流(some audio and data formats),在第一个消息之后的每个消息的第一个块应该使用这个格式。
Type 3:块没有头。流ID,消息长度,时间戳都不出现。
如果第一个消息和第二个消息的时间增量与第一个消息的时间戳相同,那么0类型的块之后必须是3类型的块而,不需要类型2的块来注册时间增量。如果类型3的块在类型0的块之后,那么类型3的时间戳增量与0类型的块的时间戳相同。
Timestamp delta:3bytes,对于类型1的块和类型2的块,本字段表示先前块的时间戳与当前块的时间戳的差值。如果增量大于等于1677215(16进制0x00ffffff),这个值必须是16777215 ,并且扩展时间戳必须出现。否则这个值就是整个的增量。
Message length:3bytes,对于类型0或类型1的块本字段表示消息的长度。
注意,这个值通常与负载长度是不相同的。
Message type id:1bytes,对于0类型和1类型的块,本字段发送消息类型。
Message stream id:4bytes,对于0类型的块,本字段存储消息流ID Extended timestamp:0-4bytes,
只有当块消息头中的普通时间戳设置为0x00ffffff时,本字段才被传送。如果普通时间戳的值小于0x00ffffff,那么本字段一定不能出现。如果时间戳字段不出现本字段也一定不能出现。类型3的块一定不能含有本字段。
Chunk data:
默认长度为128bytes,块的大小可配置,最大65535bytes,最小128bytes,块越大CPU使用率越低,但是也导致大的写入,在低带宽下产生其他内容的延迟。
总结:
RTMP协议由包头和包体(数据)组成,包头可以是四种长度:12、8、4、1bytes,即basic header + message header。
Basic header:1bytes(官方文档即上面说可能不止1byte,但实际情况只用1byte 就够了,原因:chunk basic head的长度为1~3个字节,具体长度主要是依赖chunk stream ID的长度,所谓chunk stream ID是flash server用来管理连接的客户端的信令交互的标识,在red5的文档中称之为channel ID,协议最大支持65597个streamID 从3~65599。ID 0,1,2为协议保留,0代表ID是64~319(第二个byte + 64);1代表chunk stream ID为64~65599((第三个byte)* 256 + 第二个byte + 64)(小端表示);2代表该消息为低层的协议(在RTMP协议中控制信令的chunk stream ID都是2)。3~63的chunk stream ID就是该byte的值。没有附加的字段来标识chunk stream streamID。在这里要指出的是虽然RTMP 的chunk stream ID理论是可以达到65599,但是目前使用的chunk stream ID 很少,2~7都是约定的,8是用来传输publish play等命令,其他的chunk stream ID目前好像没有使用,所以目前chunk basic head的长度一般为1个字节),由chunk type和chunk channel ID组成。Chunk type占据前两个bit,决定message header的大小,即type0,type1,type2,type3,分别为11,7,3,0bytes,它可以用掩码0xC0进行与运算。Chunk channel id占据后面6个bits,Stream ID和Channel ID对应关系为:
StreamID=(ChannelID-4)/5-1
其可以为以下内容:
02 ping和ByteRead通道
03 invoke通道,我们的connect() publish()和自字写的
NetConnection.Call() 数据都是在这个通道的
04 audio和vedio通道
05、06、07 服务器保留,经观察FMS2用这些channel也用来传送音频或
视频
在rtmp包中经常看见的0xC2,就表示type为type3,channel Id为2。