RTMP协议分析-handshake - 弦外之音

/ 0评 / 1

rtmp 是比较流行的直播协议,同时也比较古老。rtmp 的标准文档 下载地址:百度网盘,提取码:xeiu

RTMP标准 并没有规定 底层协议 是TCP 还是UDP,还是其他。不过通常RTMP服务器客户端都是基于 TCP 实现的。

本文主要讲解,RTMP协议里面的 handshake(握手)流程,机制,以及逻辑。


服务器采用 SRS 搭建,客户端使用 FFmpeg 推流,命令如下:

ffmpeg.exe -i a.mp4  -c copy -f flv rtmp://192.168.0.123/live/livestream

下图的流程摘取于标准文档。

从上图可以看到,RTMP 链接经历 3 个 状态。

1,Uninitialized,未初始化状态,只要没发 C0 或者 S0 数据包,都是初始化状态。

这里讲解一下 C0 跟 S0 是什么,就是一个8位的数据,单字节,代表 RTMP 协议的版本号。C 是client ,S 代表 Server

发版本有什么用呢?

举个例子,如果C0 是 02 代表RTMP2.0 版本,但是如果 服务器 只支持 3.0 版本的RTMP,服务器就会采取合适的动作,通常做法是终结这个链接。

采取合适的动作,通常做法是终结这个链接

这句话,是对应的标准文档的英文翻译。我个人理解一下,采取合适的动作,应该是直接close TCP 的sockefd 来终结链接。

所以 如果服务器发 S0 回去了,通常跟 C0 一样,其实我也不太懂,为什么要发 S0 回去,既然都是跟C0一样,少传一个字节不是更好?

不过他协议就这么设计的。

因为 RTMP 是基于 TCP 实现,所以 C0 实际上是一个 单字节的 TCP 包,如图:

2,Version sent,这个状态是客户端收到 S0 时候就会切换到这个状态。对服务器而已,收到 C0 就会切换到这个状态。

但实际上大多数的客户端实现,C0 + C1 是同时发送的,所以 Version sent 不存在,直接会跳到 ACK sent 状态。

那个流程图,C0+C1 同时发送不会导致问题。同时发送可以提交效率,不需要等 S0 到了 再发 C1。

3,Ack sent ,客户端发送 C2 之后就会变成 Ack sent 状态,服务器发 S2 之后就会变成 Ack sent 状态。

4,Handshake Done,握手完成状态,客户端 收到 S2 就握手完成了,服务器是 收到 C2。



RTMP 的握手流程就是这样,C0,S0 上面已经讲了,就是协商版本号。接下来讲讲 C1 跟 S1 的格式,如下图:。

RTMP 规定,所有整形字段都是网络字节序,也就是大端序。从上图可以看出,C1 跟 S1 格式是一样的,都只有 3个字段。

1,time,4字节的时间戳。

2,zero,4字节的0,填充字段,不用管。

3,random bytes,随机数,1528个字节。

所以加起来,C1 这个数据包一共是 1536 字节,会放在 TCP body 里面传输,TCP MSS机制导致 TCP body 只能放 1460 字节,所以会分成两个 TCP 包发送。如图:

从上图可以看到,两个 TCP 包才合成一个 RTMP 包,第一个TCP 包的body 是 1460 字节,第二个TCP 包的body 是 77 字节,加起来是 1537字节,比 C1 多了一个字节,为什么?因为多的一个字节是 C0 的,C0+C1同时发送。

C1 里面的 time 字段主要是用于计算 RTT 时间的,把一个本地的时间放在 C1 的time里面,然后 服务器 收到 C0+C1 之后,会立马发 S2 回去,S2 里面有之前的本地时间,这样客户端就能计算出一个来回的时间。S1 的原理跟 C1 一样。

然后随机数应该是用来加密的,后续补充,我也不太清楚。


最后还剩一个包未分析,就是 C2 跟 S2,格式如下:

这里注意,客户端必须收到 S1 之后才能发 C2,因为客户端需要把 S1 包里的 time 填到 C2 的time里面。

服务器必须收到C1之后才能发 S2,因为服务器需要把 C1 包里的 time 填到 S2 的time里面。

所以 C2/S2 里面的 time 字段的意义很明显,就是对面的本地时间。然后 time2 是自己的本地时间。

最后 C2 里面有个 random echo,存的是服务器在S1发的的随机数,又echo 回去。

这里其实我也不清楚为什么要 echo 随机数回去,因为都开始发C2了,就代表客户端收到服务器发的 S1 的随机数了,而且服务器收到C2之后,也能确认客户端已经拿到了S1的随机数。

所以,RTMP 为什么要 echo 随机数我目前不太清楚,需要看继续看源码实现,才知道随机数的具体作用。


©版权所属:知识星球:弦外之音,QQ:2338195090。

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注