本文梳理了理解RTMP协议的基本概念
访问 个人博客了解更多
下图是播放器与 rtmp 服务端通讯的例子html
另外推荐阅读 nginx-rtmp-module 源码,好比,握手协议相关代码在 ngx_rtmp_handshake.c
文件nginx
TCP 握手过程这里不详细展开,参考这篇文章 TCP 的那些事儿git
RTMP 握手起到验证的做用,RTMP 握手方式主要分为:简单握手与复杂握手github
Adobe 协议中描述的是简单握手,而 Adobe 产品 Flash Media Server 采用复杂握手的方式shell
与流程图有点不一样,握手的实际流程分三个步骤:服务器
我使用 Wireshark 抓包,验证了过程(我使用 nginx-rtmp-module 作服务器,ffmpeg推流,VLC Media Play播放)网络
报文的解释:dom
C0 与 S0 +-+-+-+-+-+-+-+-+ | version | +-+-+-+-+-+-+-+-+
C0 与 S0tcp
C1 与 S1 +-+-+-+-+-+-+-+-+-+-+ | time (4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | zero (4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | random bytes | +-+-+-+-+-+-+-+-+-+-+ |random bytes(cont) | | .... | +-+-+-+-+-+-+-+-+-+-+
C1 与 S1post
C2 与 S2 +-+-+-+-+-+-+-+-+-+-+ | time (4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | time2(4 bytes) | +-+-+-+-+-+-+-+-+-+-+ | random bytes | +-+-+-+-+-+-+-+-+-+-+ |random bytes(cont) | | .... | +-+-+-+-+-+-+-+-+-+-+
C2 与 S2
RTMP 是用于网络传输的二进制协议,默认使用 Big-Endian 格式,由于 Big-Endian 格式在抓包时可读性较好
对于复杂握手,不使用 Adobe 产品 FMS 的话,简单了解便可
相对于简单握手,复杂握手增长了严格的验证,主要是 random 字段上进行更细化的划分
1528Bytes随机数的部分平均分红两部分,一部分764Bytes存储public key(公共密钥),另外一部分764Bytes存储digest(密文,32字节)。
从二进制报文的角度,判断复杂握手的特征是,Version部分不为0,服务器端可根据这个来判断是否简单握手或复杂握手。
握手的了解到这里,下面继续看看握手以后的步骤
RTMP 有一个重要的概念:Application Instance,直观上,能够体如今 rtmp 的 url 上
我测试的推流例子,用到的 url 为: rtmp://192.168.23.152/live/movie
你们能够注意到,上面 wireshark 对 rtmp 抓包的截图中,握手后紧接一个 client->server 的报文 connect('live')
,
1909 36.398483095 192.168.23.152 192.168.23.152 RTMP 282 connect('live')
而这个 live
就是此次推流的 Application Instance
上面 wireshark 对 rtmp 抓包的截图中,有下面两行,第一行是 client->server,第二行是 server->client
1933 36.484940956 192.168.23.152 192.168.23.152 RTMP 105 Window Acknowledgement Size 5000000|createStream() 1935 36.485004644 192.168.23.152 192.168.23.152 RTMP 109 _result() 1946 36.528398367 192.168.23.152 192.168.23.152 RTMP 168 getStreamLength()|play('movie')|Set Buffer Length 1,3000ms
直观地,rtmp://192.168.23.152/live/movie 的 movie 是此次拉流的 stream
。
createStream 命令用于建立逻辑通道,该通道用于传输视频、音频、metadata。在服务器的响应报文 _result() 中会返回Stream ID,用于惟一的标示该Stream。
getStreamLength 命令用来获取 movie
的流的长度
Real Time Messaging Protocol (AMF0 Command getStreamLength()) RTMP Header RTMP Body String 'getStreamLength' Number 3 Null String 'movie' Real Time Messaging Protocol (AMF0 Command play('movie')) RTMP Header RTMP Body String 'play' Number 4 Null String 'movie' Number -2000
根据 Adobe’s Real Time Messaging Protocol 里对 _result
命令的定义,上面 body 中第四个字段 "Number 1" 即是这次的 Stream ID
通常的 rtmp 链接的流程,都如上所示,后面即是命令与音视频数据的消息,好比:
根据 Adobe’s Real Time Messaging Protocol
NetStream sends the deleteStream command when the NetStream object is getting destroyed.
当 NetStream 对象销毁的时候发送删除流命令。
好比,播放器客户端中止播放,能够删除指定Stream ID的流。服务器不用对这条命令发送响应报文。